<!doctype html>
<html lang="en-us">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="full-screen" content="true"/>
    <meta name="screen-orientation" content="portrait"/>
    <meta name="x5-fullscreen" content="true"/>
    <meta name="360-fullscreen" content="true"/>
    <title>Cody Prototype</title>
    <style>
        body {
            font-family: arial;
            -ms-touch-action: none;
            background: #FFFFFF;
            border: 0;
            margin: 0;
            height: 100%;
        }

        .cody { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
        div.cody {
            text-align: center;
            border: 0;
            margin: 0;
            height: 100%;
        }
        div.cody_border {
            border: 0;
            -webkit-tap-highlight-color: transparent;
            height: 500px;
            width: 100%;
        }
    </style>
</head>
<body style="overflow: hidden">
<div class="cody_border" id="JAXAppFrame">
</div>
<input type="file" id="JAXFileInput" style="opacity: 0; position: absolute; top: -100px"/>
<a id="JAXFileDownload" href="" style="opacity: 0; position: absolute; top: -100px"> </a>
<script type="text/javascript">
	/*!

JSZip v3.6.0 - A JavaScript class for generating and reading zip files
<http://stuartk.com/jszip>

(c) 2009-2016 Stuart Knightley <stuart [at] stuartk.com>
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.

JSZip uses the library pako released under the MIT license :
https://github.com/nodeca/pako/blob/master/LICENSE
*/

!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=e()}}(function(){return function s(a,o,u){function h(r,e){if(!o[r]){if(!a[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(f)return f(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[r]={exports:{}};a[r][0].call(i.exports,function(e){var t=a[r][1][e];return h(t||e)},i,i.exports,s,a,o,u)}return o[r].exports}for(var f="function"==typeof require&&require,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(l,t,n){(function(r){!function(e){"object"==typeof n&&void 0!==t?t.exports=e():("undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:this).JSZip=e()}(function(){return function s(a,o,u){function h(t,e){if(!o[t]){if(!a[t]){var r="function"==typeof l&&l;if(!e&&r)return r(t,!0);if(f)return f(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[t]={exports:{}};a[t][0].call(i.exports,function(e){return h(a[t][1][e]||e)},i,i.exports,s,a,o,u)}return o[t].exports}for(var f="function"==typeof l&&l,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(l,t,n){(function(r){!function(e){"object"==typeof n&&void 0!==t?t.exports=e():("undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:this).JSZip=e()}(function(){return function s(a,o,u){function h(t,e){if(!o[t]){if(!a[t]){var r="function"==typeof l&&l;if(!e&&r)return r(t,!0);if(f)return f(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[t]={exports:{}};a[t][0].call(i.exports,function(e){return h(a[t][1][e]||e)},i,i.exports,s,a,o,u)}return o[t].exports}for(var f="function"==typeof l&&l,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(l,t,n){(function(r){!function(e){"object"==typeof n&&void 0!==t?t.exports=e():("undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:this).JSZip=e()}(function(){return function s(a,o,u){function h(t,e){if(!o[t]){if(!a[t]){var r="function"==typeof l&&l;if(!e&&r)return r(t,!0);if(f)return f(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[t]={exports:{}};a[t][0].call(i.exports,function(e){return h(a[t][1][e]||e)},i,i.exports,s,a,o,u)}return o[t].exports}for(var f="function"==typeof l&&l,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(l,t,n){(function(r){!function(e){"object"==typeof n&&void 0!==t?t.exports=e():("undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:this).JSZip=e()}(function(){return function s(a,o,u){function h(t,e){if(!o[t]){if(!a[t]){var r="function"==typeof l&&l;if(!e&&r)return r(t,!0);if(f)return f(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[t]={exports:{}};a[t][0].call(i.exports,function(e){return h(a[t][1][e]||e)},i,i.exports,s,a,o,u)}return o[t].exports}for(var f="function"==typeof l&&l,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(l,t,n){(function(r){!function(e){"object"==typeof n&&void 0!==t?t.exports=e():("undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:this).JSZip=e()}(function(){return function s(a,o,u){function h(t,e){if(!o[t]){if(!a[t]){var r="function"==typeof l&&l;if(!e&&r)return r(t,!0);if(f)return f(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[t]={exports:{}};a[t][0].call(i.exports,function(e){return h(a[t][1][e]||e)},i,i.exports,s,a,o,u)}return o[t].exports}for(var f="function"==typeof l&&l,e=0;e<u.length;e++)h(u[e]);return h}({1:[function(e,t,r){"use strict";var c=e("./utils"),l=e("./support"),p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.encode=function(e){for(var t,r,n,i,s,a,o,u=[],h=0,f=e.length,l=f,d="string"!==c.getTypeOf(e);h<e.length;)l=f-h,n=d?(t=e[h++],r=h<f?e[h++]:0,h<f?e[h++]:0):(t=e.charCodeAt(h++),r=h<f?e.charCodeAt(h++):0,h<f?e.charCodeAt(h++):0),i=t>>2,s=(3&t)<<4|r>>4,a=1<l?(15&r)<<2|n>>6:64,o=2<l?63&n:64,u.push(p.charAt(i)+p.charAt(s)+p.charAt(a)+p.charAt(o));return u.join("")},r.decode=function(e){var t,r,n,i,s,a,o=0,u=0;if("data:"===e.substr(0,"data:".length))throw new Error("Invalid base64 input, it looks like a data url.");var h,f=3*(e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"")).length/4;if(e.charAt(e.length-1)===p.charAt(64)&&f--,e.charAt(e.length-2)===p.charAt(64)&&f--,f%1!=0)throw new Error("Invalid base64 input, bad content length.");for(h=l.uint8array?new Uint8Array(0|f):new Array(0|f);o<e.length;)t=p.indexOf(e.charAt(o++))<<2|(i=p.indexOf(e.charAt(o++)))>>4,r=(15&i)<<4|(s=p.indexOf(e.charAt(o++)))>>2,n=(3&s)<<6|(a=p.indexOf(e.charAt(o++))),h[u++]=t,64!==s&&(h[u++]=r),64!==a&&(h[u++]=n);return h}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(e){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils"),a=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r){var n=a,i=0+r;e^=-1;for(var s=0;s<i;s++)e=e>>>8^n[255&(e^t[s])];return-1^e}(0|t,e,e.length):function(e,t,r){var n=a,i=0+r;e^=-1;for(var s=0;s<i;s++)e=e>>>8^n[255&(e^t.charCodeAt(s))];return-1^e}(0|t,e,e.length):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function u(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(u,a),u.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},u.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},u.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},u.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var t=this;this._pako.onData=function(e){t.push({data:e,meta:t.meta})}},r.compressWorker=function(e){return new u("Deflate",e)},r.uncompressWorker=function(){return new u("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function I(e,t){var r,n="";for(r=0;r<t;r++)n+=String.fromCharCode(255&e),e>>>=8;return n}function i(e,t,r,n,i,s){var a,o,u=e.file,h=e.compression,f=s!==B.utf8encode,l=O.transformTo("string",s(u.name)),d=O.transformTo("string",B.utf8encode(u.name)),c=u.comment,p=O.transformTo("string",s(c)),m=O.transformTo("string",B.utf8encode(c)),_=d.length!==u.name.length,g=m.length!==c.length,v="",b="",w="",y=u.dir,k=u.date,x={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(x.crc32=e.crc32,x.compressedSize=e.compressedSize,x.uncompressedSize=e.uncompressedSize);var S=0;t&&(S|=8),f||!_&&!g||(S|=2048);var z,E=0,C=0;y&&(E|=16),"UNIX"===i?(C=798,E|=((z=u.unixPermissions)||(z=y?16893:33204),(65535&z)<<16)):(C=20,E|=63&(u.dosPermissions||0)),a=k.getUTCHours(),a<<=6,a|=k.getUTCMinutes(),a<<=5,a|=k.getUTCSeconds()/2,o=k.getUTCFullYear()-1980,o<<=4,o|=k.getUTCMonth()+1,o<<=5,o|=k.getUTCDate(),_&&(v+="up"+I((b=I(1,1)+I(T(l),4)+d).length,2)+b),g&&(v+="uc"+I((w=I(1,1)+I(T(p),4)+m).length,2)+w);var A="";return A+="\n\0",A+=I(S,2),A+=h.magic,A+=I(a,2),A+=I(o,2),A+=I(x.crc32,4),A+=I(x.compressedSize,4),A+=I(x.uncompressedSize,4),A+=I(l.length,2),A+=I(v.length,2),{fileRecord:R.LOCAL_FILE_HEADER+A+l+v,dirRecord:R.CENTRAL_FILE_HEADER+I(C,2)+A+I(p.length,2)+"\0\0\0\0"+I(E,4)+I(n,4)+l+v+p}}var O=e("../utils"),s=e("../stream/GenericWorker"),B=e("../utf8"),T=e("../crc32"),R=e("../signature");function n(e,t,r,n){s.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}O.inherits(n,s),n.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,s.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},n.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=i(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},n.prototype.closedSource=function(e){this.accumulate=!1;var t,r=this.streamFiles&&!e.file.dir,n=i(e,r,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(n.dirRecord),r)this.push({data:(t=e,R.DATA_DESCRIPTOR+I(t.crc32,4)+I(t.compressedSize,4)+I(t.uncompressedSize,4)),meta:{percent:100}});else for(this.push({data:n.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},n.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t<this.dirRecords.length;t++)this.push({data:this.dirRecords[t],meta:{percent:100}});var r,n,i,s,a,o,u=this.bytesWritten-e,h=(r=this.dirRecords.length,n=u,i=e,s=this.zipComment,a=this.encodeFileName,o=O.transformTo("string",a(s)),R.CENTRAL_DIRECTORY_END+"\0\0\0\0"+I(r,2)+I(r,2)+I(n,4)+I(i,4)+I(o.length,2)+o);this.push({data:h,meta:{percent:100}})},n.prototype.prepareNextSource=function(){this.previous=this._sources.shift(),this.openedSource(this.previous.streamInfo),this.isPaused?this.previous.pause():this.previous.resume()},n.prototype.registerPrevious=function(e){this._sources.push(e);var t=this;return e.on("data",function(e){t.processChunk(e)}),e.on("end",function(){t.closedSource(t.previous.streamInfo),t._sources.length?t.prepareNextSource():t.end()}),e.on("error",function(e){t.error(e)}),this},n.prototype.resume=function(){return!!s.prototype.resume.call(this)&&(!this.previous&&this._sources.length?(this.prepareNextSource(),!0):this.previous||this._sources.length||this.generatedError?void 0:(this.end(),!0))},n.prototype.error=function(e){var t=this._sources;if(!s.prototype.error.call(this,e))return!1;for(var r=0;r<t.length;r++)try{t[r].error(e)}catch(e){}return!0},n.prototype.lock=function(){s.prototype.lock.call(this);for(var e=this._sources,t=0;t<e.length;t++)e[t].lock()},t.exports=n},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(e,t,r){"use strict";var h=e("../compressions"),n=e("./ZipFileWorker");r.generateWorker=function(e,a,t){var o=new n(a.streamFiles,t,a.platform,a.encodeFileName),u=0;try{e.forEach(function(e,t){u++;var r=function(e,t){var r=e||t,n=h[r];if(!n)throw new Error(r+" is not a valid compression method !");return n}(t.options.compression,a.compression),n=t.options.compressionOptions||a.compressionOptions||{},i=t.dir,s=t.date;t._compressWorker(r,n).withStreamInfo("file",{name:e,dir:i,date:s,comment:t.comment||"",unixPermissions:t.unixPermissions,dosPermissions:t.dosPermissions}).pipe(o)}),o.entriesCount=u}catch(e){o.error(e)}return o}},{"../compressions":3,"./ZipFileWorker":8}],10:[function(e,t,r){"use strict";function n(){if(!(this instanceof n))return new n;if(arguments.length)throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");this.files={},this.comment=null,this.root="",this.clone=function(){var e=new n;for(var t in this)"function"!=typeof this[t]&&(e[t]=this[t]);return e}}(n.prototype=e("./object")).loadAsync=e("./load"),n.support=e("./support"),n.defaults=e("./defaults"),n.version="3.5.0",n.loadAsync=function(e,t){return(new n).loadAsync(e,t)},n.external=e("./external"),t.exports=n},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(e,t,r){"use strict";var n=e("./utils"),i=e("./external"),o=e("./utf8"),u=e("./zipEntries"),s=e("./stream/Crc32Probe"),h=e("./nodejsUtils");function f(n){return new i.Promise(function(e,t){var r=n.decompressed.getContentWorker().pipe(new s);r.on("error",function(e){t(e)}).on("end",function(){r.streamInfo.crc32!==n.decompressed.crc32?t(new Error("Corrupted zip : CRC32 mismatch")):e()}).resume()})}t.exports=function(e,s){var a=this;return s=n.extend(s||{},{base64:!1,checkCRC32:!1,optimizedBinaryString:!1,createFolders:!1,decodeFileName:o.utf8decode}),h.isNode&&h.isStream(e)?i.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")):n.prepareContent("the loaded zip file",e,!0,s.optimizedBinaryString,s.base64).then(function(e){var t=new u(s);return t.load(e),t}).then(function(e){var t=[i.Promise.resolve(e)],r=e.files;if(s.checkCRC32)for(var n=0;n<r.length;n++)t.push(f(r[n]));return i.Promise.all(t)}).then(function(e){for(var t=e.shift(),r=t.files,n=0;n<r.length;n++){var i=r[n];a.file(i.fileNameStr,i.decompressed,{binary:!0,optimizedBinaryString:!0,date:i.date,dir:i.dir,comment:i.fileCommentStr.length?i.fileCommentStr:null,unixPermissions:i.unixPermissions,dosPermissions:i.dosPermissions,createFolders:s.createFolders})}return t.zipComment.length&&(a.comment=t.zipComment),a})}},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../stream/GenericWorker");function s(e,t){i.call(this,"Nodejs stream input adapter for "+e),this._upstreamEnded=!1,this._bindStream(t)}n.inherits(s,i),s.prototype._bindStream=function(e){var t=this;(this._stream=e).pause(),e.on("data",function(e){t.push({data:e,meta:{percent:0}})}).on("error",function(e){t.isPaused?this.generatedError=e:t.error(e)}).on("end",function(){t.isPaused?t._upstreamEnded=!0:t.end()})},s.prototype.pause=function(){return!!i.prototype.pause.call(this)&&(this._stream.pause(),!0)},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(this._upstreamEnded?this.end():this._stream.resume(),!0)},t.exports=s},{"../stream/GenericWorker":28,"../utils":32}],13:[function(e,t,r){"use strict";var i=e("readable-stream").Readable;function n(e,t,r){i.call(this,t),this._helper=e;var n=this;e.on("data",function(e,t){n.push(e)||n._helper.pause(),r&&r(t)}).on("error",function(e){n.emit("error",e)}).on("end",function(){n.push(null)})}e("../utils").inherits(n,i),n.prototype._read=function(){this._helper.resume()},t.exports=n},{"../utils":32,"readable-stream":16}],14:[function(e,t,r){"use strict";t.exports={isNode:"undefined"!=typeof Buffer,newBufferFrom:function(e,t){if(Buffer.from&&Buffer.from!==Uint8Array.from)return Buffer.from(e,t);if("number"==typeof e)throw new Error('The "data" argument must not be a number');return new Buffer(e,t)},allocBuffer:function(e){if(Buffer.alloc)return Buffer.alloc(e);var t=new Buffer(e);return t.fill(0),t},isBuffer:function(e){return Buffer.isBuffer(e)},isStream:function(e){return e&&"function"==typeof e.on&&"function"==typeof e.pause&&"function"==typeof e.resume}}},{}],15:[function(e,t,r){"use strict";function s(e,t,r){var n,i=f.getTypeOf(t),s=f.extend(r||{},d);s.date=s.date||new Date,null!==s.compression&&(s.compression=s.compression.toUpperCase()),"string"==typeof s.unixPermissions&&(s.unixPermissions=parseInt(s.unixPermissions,8)),s.unixPermissions&&16384&s.unixPermissions&&(s.dir=!0),s.dosPermissions&&16&s.dosPermissions&&(s.dir=!0),s.dir&&(e=h(e)),s.createFolders&&(n=function(e){"/"===e.slice(-1)&&(e=e.substring(0,e.length-1));var t=e.lastIndexOf("/");return 0<t?e.substring(0,t):""}(e))&&g.call(this,n,!0);var a,o="string"===i&&!1===s.binary&&!1===s.base64;r&&void 0!==r.binary||(s.binary=!o),(t instanceof c&&0===t.uncompressedSize||s.dir||!t||0===t.length)&&(s.base64=!1,s.binary=!0,t="",s.compression="STORE",i="string"),a=t instanceof c||t instanceof l?t:m.isNode&&m.isStream(t)?new _(e,t):f.prepareContent(e,t,s.binary,s.optimizedBinaryString,s.base64);var u=new p(e,a,s);this.files[e]=u}function h(e){return"/"!==e.slice(-1)&&(e+="/"),e}var i=e("./utf8"),f=e("./utils"),l=e("./stream/GenericWorker"),a=e("./stream/StreamHelper"),d=e("./defaults"),c=e("./compressedObject"),p=e("./zipObject"),o=e("./generate"),m=e("./nodejsUtils"),_=e("./nodejs/NodejsStreamInputAdapter"),g=function(e,t){return t=void 0!==t?t:d.createFolders,e=h(e),this.files[e]||s.call(this,e,null,{dir:!0,createFolders:t}),this.files[e]};function u(e){return"[object RegExp]"===Object.prototype.toString.call(e)}var n={load:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},forEach:function(e){var t,r,n;for(t in this.files)this.files.hasOwnProperty(t)&&(n=this.files[t],(r=t.slice(this.root.length,t.length))&&t.slice(0,this.root.length)===this.root&&e(r,n))},filter:function(r){var n=[];return this.forEach(function(e,t){r(e,t)&&n.push(t)}),n},file:function(e,t,r){if(1!==arguments.length)return e=this.root+e,s.call(this,e,t,r),this;if(u(e)){var n=e;return this.filter(function(e,t){return!t.dir&&n.test(e)})}var i=this.files[this.root+e];return i&&!i.dir?i:null},folder:function(r){if(!r)return this;if(u(r))return this.filter(function(e,t){return t.dir&&r.test(e)});var e=this.root+r,t=g.call(this,e),n=this.clone();return n.root=t.name,n},remove:function(r){r=this.root+r;var e=this.files[r];if(e||("/"!==r.slice(-1)&&(r+="/"),e=this.files[r]),e&&!e.dir)delete this.files[r];else for(var t=this.filter(function(e,t){return t.name.slice(0,r.length)===r}),n=0;n<t.length;n++)delete this.files[t[n].name];return this},generate:function(e){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},generateInternalStream:function(e){var t,r={};try{if((r=f.extend(e||{},{streamFiles:!1,compression:"STORE",compressionOptions:null,type:"",platform:"DOS",comment:null,mimeType:"application/zip",encodeFileName:i.utf8encode})).type=r.type.toLowerCase(),r.compression=r.compression.toUpperCase(),"binarystring"===r.type&&(r.type="string"),!r.type)throw new Error("No output type specified.");f.checkSupport(r.type),"darwin"!==r.platform&&"freebsd"!==r.platform&&"linux"!==r.platform&&"sunos"!==r.platform||(r.platform="UNIX"),"win32"===r.platform&&(r.platform="DOS");var n=r.comment||this.comment||"";t=o.generateWorker(this,r,n)}catch(e){(t=new l("error")).error(e)}return new a(t,r.type||"string",r.mimeType)},generateAsync:function(e,t){return this.generateInternalStream(e).accumulate(t)},generateNodeStream:function(e,t){return(e=e||{}).type||(e.type="nodebuffer"),this.generateInternalStream(e).toNodejsStream(t)}};t.exports=n},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(e,t,r){t.exports=e("stream")},{stream:void 0}],17:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e);for(var t=0;t<this.data.length;t++)e[t]=255&e[t]}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data[this.zero+e]},i.prototype.lastIndexOfSignature=function(e){for(var t=e.charCodeAt(0),r=e.charCodeAt(1),n=e.charCodeAt(2),i=e.charCodeAt(3),s=this.length-4;0<=s;--s)if(this.data[s]===t&&this.data[s+1]===r&&this.data[s+2]===n&&this.data[s+3]===i)return s-this.zero;return-1},i.prototype.readAndCheckSignature=function(e){var t=e.charCodeAt(0),r=e.charCodeAt(1),n=e.charCodeAt(2),i=e.charCodeAt(3),s=this.readData(4);return t===s[0]&&r===s[1]&&n===s[2]&&i===s[3]},i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return[];var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],18:[function(e,t,r){"use strict";var n=e("../utils");function i(e){this.data=e,this.length=e.length,this.index=0,this.zero=0}i.prototype={checkOffset:function(e){this.checkIndex(this.index+e)},checkIndex:function(e){if(this.length<this.zero+e||e<0)throw new Error("End of data reached (data length = "+this.length+", asked index = "+e+"). Corrupted zip ?")},setIndex:function(e){this.checkIndex(e),this.index=e},skip:function(e){this.setIndex(this.index+e)},byteAt:function(e){},readInt:function(e){var t,r=0;for(this.checkOffset(e),t=this.index+e-1;t>=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(e){},lastIndexOfSignature:function(e){},readAndCheckSignature:function(e){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),u=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new u(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r<this._listeners[e].length;r++)this._listeners[e][r].call(this,t)},pipe:function(e){return e.registerPrevious(this)},registerPrevious:function(e){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.streamInfo=e.streamInfo,this.mergeStreamInfo(),this.previous=e;var t=this;return e.on("data",function(e){t.processChunk(e)}),e.on("end",function(){t.end()}),e.on("error",function(e){t.error(e)}),this},pause:function(){return!this.isPaused&&!this.isFinished&&(this.isPaused=!0,this.previous&&this.previous.pause(),!0)},resume:function(){if(!this.isPaused||this.isFinished)return!1;var e=this.isPaused=!1;return this.generatedError&&(this.error(this.generatedError),e=!0),this.previous&&this.previous.resume(),!e},flush:function(){},processChunk:function(e){this.push(e)},withStreamInfo:function(e,t){return this.extraStreamInfo[e]=t,this.mergeStreamInfo(),this},mergeStreamInfo:function(){for(var e in this.extraStreamInfo)this.extraStreamInfo.hasOwnProperty(e)&&(this.streamInfo[e]=this.extraStreamInfo[e])},lock:function(){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.isLocked=!0,this.previous&&this.previous.lock()},toString:function(){var e="Worker "+this.name;return this.previous?this.previous+" -> "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var h=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),f=e("../base64"),n=e("../support"),a=e("../external"),o=null;if(n.nodestream)try{o=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function u(e,t,r){var n=t;switch(t){case"blob":case"arraybuffer":n="uint8array";break;case"base64":n="string"}try{this._internalType=n,this._outputType=t,this._mimeType=r,h.checkSupport(n),this._worker=e.pipe(new i(n)),e.lock()}catch(e){this._worker=new s("error"),this._worker.error(e)}}u.prototype={accumulate:function(e){return o=this,u=e,new a.Promise(function(t,r){var n=[],i=o._internalType,s=o._outputType,a=o._mimeType;o.on("data",function(e,t){n.push(e),u&&u(t)}).on("error",function(e){n=[],r(e)}).on("end",function(){try{var e=function(e,t,r){switch(e){case"blob":return h.newBlob(h.transformTo("arraybuffer",t),r);case"base64":return f.encode(t);default:return h.transformTo(e,t)}}(s,function(e,t){var r,n=0,i=null,s=0;for(r=0;r<t.length;r++)s+=t[r].length;switch(e){case"string":return t.join("");case"array":return Array.prototype.concat.apply([],t);case"uint8array":for(i=new Uint8Array(s),r=0;r<t.length;r++)i.set(t[r],n),n+=t[r].length;return i;case"nodebuffer":return Buffer.concat(t);default:throw new Error("concat : unsupported type '"+e+"'")}}(i,n),a);t(e)}catch(e){r(e)}n=[]}).resume()});var o,u},on:function(e,t){var r=this;return"data"===e?this._worker.on(e,function(e){t.call(r,e.data,e.meta)}):this._worker.on(e,function(){h.delay(t,arguments,r)}),this},resume:function(){return h.delay(this._worker.resume,[],this._worker),this},pause:function(){return this._worker.pause(),this},toNodejsStream:function(e){if(h.checkSupport("nodestream"),"nodebuffer"!==this._outputType)throw new Error(this._outputType+" is not supported by this method");return new o(this,{objectMode:"nodebuffer"!==this._outputType},e)}},t.exports=u},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(e,t,r){"use strict";if(r.base64=!0,r.array=!0,r.string=!0,r.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,r.nodebuffer="undefined"!=typeof Buffer,r.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)r.blob=!1;else{var n=new ArrayBuffer(0);try{r.blob=0===new Blob([n],{type:"application/zip"}).size}catch(e){try{var i=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);i.append(n),r.blob=0===i.getBlob("application/zip").size}catch(e){r.blob=!1}}}try{r.nodestream=!!e("readable-stream").Readable}catch(e){r.nodestream=!1}},{"readable-stream":16}],31:[function(e,t,s){"use strict";for(var o=e("./utils"),u=e("./support"),r=e("./nodejsUtils"),n=e("./stream/GenericWorker"),h=new Array(256),i=0;i<256;i++)h[i]=252<=i?6:248<=i?5:240<=i?4:224<=i?3:192<=i?2:1;function a(){n.call(this,"utf-8 decode"),this.leftOver=null}function f(){n.call(this,"utf-8 encode")}h[254]=h[254]=1,s.utf8encode=function(e){return u.nodebuffer?r.newBufferFrom(e,"utf-8"):function(e){var t,r,n,i,s,a=e.length,o=0;for(i=0;i<a;i++)55296==(64512&(r=e.charCodeAt(i)))&&i+1<a&&56320==(64512&(n=e.charCodeAt(i+1)))&&(r=65536+(r-55296<<10)+(n-56320),i++),o+=r<128?1:r<2048?2:r<65536?3:4;for(t=u.uint8array?new Uint8Array(o):new Array(o),i=s=0;s<o;i++)55296==(64512&(r=e.charCodeAt(i)))&&i+1<a&&56320==(64512&(n=e.charCodeAt(i+1)))&&(r=65536+(r-55296<<10)+(n-56320),i++),r<128?t[s++]=r:(r<2048?t[s++]=192|r>>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t}(e)},s.utf8decode=function(e){return u.nodebuffer?o.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,n,i,s=e.length,a=new Array(2*s);for(t=r=0;t<s;)if((n=e[t++])<128)a[r++]=n;else if(4<(i=h[n]))a[r++]=65533,t+=i-1;else{for(n&=2===i?31:3===i?15:7;1<i&&t<s;)n=n<<6|63&e[t++],i--;1<i?a[r++]=65533:n<65536?a[r++]=n:(n-=65536,a[r++]=55296|n>>10&1023,a[r++]=56320|1023&n)}return a.length!==r&&(a.subarray?a=a.subarray(0,r):a.length=r),o.applyFromCharCode(a)}(e=o.transformTo(u.uint8array?"uint8array":"array",e))},o.inherits(a,n),a.prototype.processChunk=function(e){var t=o.transformTo(u.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(u.uint8array){var r=t;(t=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),t.set(r,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var n=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+h[e[r]]>t?r:t}(t),i=t;n!==t.length&&(u.uint8array?(i=t.subarray(0,n),this.leftOver=t.subarray(n,t.length)):(i=t.slice(0,n),this.leftOver=t.slice(n,t.length))),this.push({data:s.utf8decode(i),meta:e.meta})},a.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=a,o.inherits(f,n),f.prototype.processChunk=function(e){this.push({data:s.utf8encode(e.data),meta:e.meta})},s.Utf8EncodeWorker=f},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,o){"use strict";var u=e("./support"),h=e("./base64"),r=e("./nodejsUtils"),n=e("set-immediate-shim"),f=e("./external");function i(e){return e}function l(e,t){for(var r=0;r<e.length;++r)t[r]=255&e.charCodeAt(r);return t}o.newBlob=function(t,r){o.checkSupport("blob");try{return new Blob([t],{type:r})}catch(e){try{var n=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);return n.append(t),n.getBlob(r)}catch(e){throw new Error("Bug : can't construct the Blob.")}}};var s={stringifyByChunk:function(e,t,r){var n=[],i=0,s=e.length;if(s<=r)return String.fromCharCode.apply(null,e);for(;i<s;)"array"===t||"nodebuffer"===t?n.push(String.fromCharCode.apply(null,e.slice(i,Math.min(i+r,s)))):n.push(String.fromCharCode.apply(null,e.subarray(i,Math.min(i+r,s)))),i+=r;return n.join("")},stringifyByChar:function(e){for(var t="",r=0;r<e.length;r++)t+=String.fromCharCode(e[r]);return t},applyCanBeUsed:{uint8array:function(){try{return u.uint8array&&1===String.fromCharCode.apply(null,new Uint8Array(1)).length}catch(e){return!1}}(),nodebuffer:function(){try{return u.nodebuffer&&1===String.fromCharCode.apply(null,r.allocBuffer(1)).length}catch(e){return!1}}()}};function a(e){var t=65536,r=o.getTypeOf(e),n=!0;if("uint8array"===r?n=s.applyCanBeUsed.uint8array:"nodebuffer"===r&&(n=s.applyCanBeUsed.nodebuffer),n)for(;1<t;)try{return s.stringifyByChunk(e,r,t)}catch(e){t=Math.floor(t/2)}return s.stringifyByChar(e)}function d(e,t){for(var r=0;r<e.length;r++)t[r]=e[r];return t}o.applyFromCharCode=a;var c={};c.string={string:i,array:function(e){return l(e,new Array(e.length))},arraybuffer:function(e){return c.string.uint8array(e).buffer},uint8array:function(e){return l(e,new Uint8Array(e.length))},nodebuffer:function(e){return l(e,r.allocBuffer(e.length))}},c.array={string:a,array:i,arraybuffer:function(e){return new Uint8Array(e).buffer},uint8array:function(e){return new Uint8Array(e)},nodebuffer:function(e){return r.newBufferFrom(e)}},c.arraybuffer={string:function(e){return a(new Uint8Array(e))},array:function(e){return d(new Uint8Array(e),new Array(e.byteLength))},arraybuffer:i,uint8array:function(e){return new Uint8Array(e)},nodebuffer:function(e){return r.newBufferFrom(new Uint8Array(e))}},c.uint8array={string:a,array:function(e){return d(e,new Array(e.length))},arraybuffer:function(e){return e.buffer},uint8array:i,nodebuffer:function(e){return r.newBufferFrom(e)}},c.nodebuffer={string:a,array:function(e){return d(e,new Array(e.length))},arraybuffer:function(e){return c.nodebuffer.uint8array(e).buffer},uint8array:function(e){return d(e,new Uint8Array(e.length))},nodebuffer:i},o.transformTo=function(e,t){if(t=t||"",!e)return t;o.checkSupport(e);var r=o.getTypeOf(t);return c[r][e](t)},o.getTypeOf=function(e){return"string"==typeof e?"string":"[object Array]"===Object.prototype.toString.call(e)?"array":u.nodebuffer&&r.isBuffer(e)?"nodebuffer":u.uint8array&&e instanceof Uint8Array?"uint8array":u.arraybuffer&&e instanceof ArrayBuffer?"arraybuffer":void 0},o.checkSupport=function(e){if(!u[e.toLowerCase()])throw new Error(e+" is not supported by this platform")},o.MAX_VALUE_16BITS=65535,o.MAX_VALUE_32BITS=-1,o.pretty=function(e){var t,r,n="";for(r=0;r<(e||"").length;r++)n+="\\x"+((t=e.charCodeAt(r))<16?"0":"")+t.toString(16).toUpperCase();return n},o.delay=function(e,t,r){n(function(){e.apply(r||null,t||[])})},o.inherits=function(e,t){function r(){}r.prototype=t.prototype,e.prototype=new r},o.extend=function(){var e,t,r={};for(e=0;e<arguments.length;e++)for(t in arguments[e])arguments[e].hasOwnProperty(t)&&void 0===r[t]&&(r[t]=arguments[e][t]);return r},o.prepareContent=function(n,e,i,s,a){return f.Promise.resolve(e).then(function(n){return u.blob&&(n instanceof Blob||-1!==["[object File]","[object Blob]"].indexOf(Object.prototype.toString.call(n)))&&"undefined"!=typeof FileReader?new f.Promise(function(t,r){var e=new FileReader;e.onload=function(e){t(e.target.result)},e.onerror=function(e){r(e.target.error)},e.readAsArrayBuffer(n)}):n}).then(function(e){var t,r=o.getTypeOf(e);return r?("arraybuffer"===r?e=o.transformTo("uint8array",e):"string"===r&&(a?e=h.decode(e):i&&!0!==s&&(e=l(t=e,u.uint8array?new Uint8Array(t.length):new Array(t.length)))),e):f.Promise.reject(new Error("Can't read the data of '"+n+"'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?"))})}},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"set-immediate-shim":54}],33:[function(e,t,r){"use strict";var n=e("./reader/readerFor"),i=e("./utils"),s=e("./signature"),a=e("./zipEntry"),o=(e("./utf8"),e("./support"));function u(e){this.files=[],this.loadOptions=e}u.prototype={checkSignature:function(e){if(!this.reader.readAndCheckSignature(e)){this.reader.index-=4;var t=this.reader.readString(4);throw new Error("Corrupted zip or bug: unexpected signature ("+i.pretty(t)+", expected "+i.pretty(e)+")")}},isSignature:function(e,t){var r=this.reader.index;this.reader.setIndex(e);var n=this.reader.readString(4)===t;return this.reader.setIndex(r),n},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2);var e=this.reader.readData(this.zipCommentLength),t=o.uint8array?"uint8array":"array",r=i.transformTo(t,e);this.zipComment=this.loadOptions.decodeFileName(r)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.reader.skip(4),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var e,t,r,n=this.zip64EndOfCentralSize-44;0<n;)e=this.reader.readInt(2),t=this.reader.readInt(4),r=this.reader.readData(t),this.zip64ExtensibleData[e]={id:e,length:t,value:r}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),1<this.disksCount)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var e,t;for(e=0;e<this.files.length;e++)t=this.files[e],this.reader.setIndex(t.localHeaderOffset),this.checkSignature(s.LOCAL_FILE_HEADER),t.readLocalPart(this.reader),t.handleUTF8(),t.processAttributes()},readCentralDir:function(){var e;for(this.reader.setIndex(this.centralDirOffset);this.reader.readAndCheckSignature(s.CENTRAL_FILE_HEADER);)(e=new a({zip64:this.zip64},this.loadOptions)).readCentralPart(this.reader),this.files.push(e);if(this.centralDirRecords!==this.files.length&&0!==this.centralDirRecords&&0===this.files.length)throw new Error("Corrupted zip or bug: expected "+this.centralDirRecords+" records in central dir, got "+this.files.length)},readEndOfCentral:function(){var e=this.reader.lastIndexOfSignature(s.CENTRAL_DIRECTORY_END);if(e<0)throw this.isSignature(0,s.LOCAL_FILE_HEADER)?new Error("Corrupted zip: can't find end of central directory"):new Error("Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html");this.reader.setIndex(e);var t=e;if(this.checkSignature(s.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===i.MAX_VALUE_16BITS||this.diskWithCentralDirStart===i.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===i.MAX_VALUE_16BITS||this.centralDirRecords===i.MAX_VALUE_16BITS||this.centralDirSize===i.MAX_VALUE_32BITS||this.centralDirOffset===i.MAX_VALUE_32BITS){if(this.zip64=!0,(e=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR))<0)throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator");if(this.reader.setIndex(e),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),!this.isSignature(this.relativeOffsetEndOfZip64CentralDir,s.ZIP64_CENTRAL_DIRECTORY_END)&&(this.relativeOffsetEndOfZip64CentralDir=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.relativeOffsetEndOfZip64CentralDir<0))throw new Error("Corrupted zip: can't find the ZIP64 end of central directory");this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}var r=this.centralDirOffset+this.centralDirSize;this.zip64&&(r+=20,r+=12+this.zip64EndOfCentralSize);var n=t-r;if(0<n)this.isSignature(t,s.CENTRAL_FILE_HEADER)||(this.reader.zero=n);else if(n<0)throw new Error("Corrupted zip: missing "+Math.abs(n)+" bytes.")},prepareReader:function(e){this.reader=n(e)},load:function(e){this.prepareReader(e),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},t.exports=u},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(e,t,r){"use strict";var n=e("./reader/readerFor"),s=e("./utils"),i=e("./compressedObject"),a=e("./crc32"),o=e("./utf8"),u=e("./compressions"),h=e("./support");function f(e,t){this.options=e,this.loadOptions=t}f.prototype={isEncrypted:function(){return 1==(1&this.bitFlag)},useUTF8:function(){return 2048==(2048&this.bitFlag)},readLocalPart:function(e){var t,r;if(e.skip(22),this.fileNameLength=e.readInt(2),r=e.readInt(2),this.fileName=e.readData(this.fileNameLength),e.skip(r),-1===this.compressedSize||-1===this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough information from the central directory (compressedSize === -1 || uncompressedSize === -1)");if(null===(t=function(e){for(var t in u)if(u.hasOwnProperty(t)&&u[t].magic===e)return u[t];return null}(this.compressionMethod)))throw new Error("Corrupted zip : compression "+s.pretty(this.compressionMethod)+" unknown (inner file : "+s.transformTo("string",this.fileName)+")");this.decompressed=new i(this.compressedSize,this.uncompressedSize,this.crc32,t,e.readData(this.compressedSize))},readCentralPart:function(e){this.versionMadeBy=e.readInt(2),e.skip(2),this.bitFlag=e.readInt(2),this.compressionMethod=e.readString(2),this.date=e.readDate(),this.crc32=e.readInt(4),this.compressedSize=e.readInt(4),this.uncompressedSize=e.readInt(4);var t=e.readInt(2);if(this.extraFieldsLength=e.readInt(2),this.fileCommentLength=e.readInt(2),this.diskNumberStart=e.readInt(2),this.internalFileAttributes=e.readInt(2),this.externalFileAttributes=e.readInt(4),this.localHeaderOffset=e.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");e.skip(t),this.readExtraFields(e),this.parseZIP64ExtraField(e),this.fileComment=e.readData(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var e=this.versionMadeBy>>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(e){if(this.extraFields[1]){var t=n(this.extraFields[1].value);this.uncompressedSize===s.MAX_VALUE_32BITS&&(this.uncompressedSize=t.readInt(8)),this.compressedSize===s.MAX_VALUE_32BITS&&(this.compressedSize=t.readInt(8)),this.localHeaderOffset===s.MAX_VALUE_32BITS&&(this.localHeaderOffset=t.readInt(8)),this.diskNumberStart===s.MAX_VALUE_32BITS&&(this.diskNumberStart=t.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4<i;)t=e.readInt(2),r=e.readInt(2),n=e.readData(r),this.extraFields[t]={id:t,length:r,value:n};e.setIndex(i)},handleUTF8:function(){var e=h.uint8array?"uint8array":"array";if(this.useUTF8())this.fileNameStr=o.utf8decode(this.fileName),this.fileCommentStr=o.utf8decode(this.fileComment);else{var t=this.findExtraFieldUnicodePath();if(null!==t)this.fileNameStr=t;else{var r=s.transformTo(e,this.fileName);this.fileNameStr=this.loadOptions.decodeFileName(r)}var n=this.findExtraFieldUnicodeComment();if(null!==n)this.fileCommentStr=n;else{var i=s.transformTo(e,this.fileComment);this.fileCommentStr=this.loadOptions.decodeFileName(i)}}},findExtraFieldUnicodePath:function(){var e=this.extraFields[28789];if(e){var t=n(e.value);return 1!==t.readInt(1)?null:a(this.fileName)!==t.readInt(4)?null:o.utf8decode(t.readData(e.length-5))}return null},findExtraFieldUnicodeComment:function(){var e=this.extraFields[25461];if(e){var t=n(e.value);return 1!==t.readInt(1)?null:a(this.fileComment)!==t.readInt(4)?null:o.utf8decode(t.readData(e.length-5))}return null}},t.exports=f},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(e,t,r){"use strict";function n(e,t,r){this.name=e,this.dir=r.dir,this.date=r.date,this.comment=r.comment,this.unixPermissions=r.unixPermissions,this.dosPermissions=r.dosPermissions,this._data=t,this._dataBinary=r.binary,this.options={compression:r.compression,compressionOptions:r.compressionOptions}}var s=e("./stream/StreamHelper"),i=e("./stream/DataWorker"),a=e("./utf8"),o=e("./compressedObject"),u=e("./stream/GenericWorker");n.prototype={internalStream:function(e){var t=null,r="string";try{if(!e)throw new Error("No output type specified.");var n="string"===(r=e.toLowerCase())||"text"===r;"binarystring"!==r&&"text"!==r||(r="string"),t=this._decompressWorker();var i=!this._dataBinary;i&&!n&&(t=t.pipe(new a.Utf8EncodeWorker)),!i&&n&&(t=t.pipe(new a.Utf8DecodeWorker))}catch(e){(t=new u("error")).error(e)}return new s(t,r,"")},async:function(e,t){return this.internalStream(e).accumulate(t)},nodeStream:function(e,t){return this.internalStream(e||"nodebuffer").toNodejsStream(t)},_compressWorker:function(e,t){if(this._data instanceof o&&this._data.compression.magic===e.magic)return this._data.getCompressedWorker();var r=this._decompressWorker();return this._dataBinary||(r=r.pipe(new a.Utf8EncodeWorker)),o.createWorkerFrom(r,e,t)},_decompressWorker:function(){return this._data instanceof o?this._data.getContentWorker():this._data instanceof u?this._data:new i(this._data)}};for(var h=["asText","asBinary","asNodeBuffer","asUint8Array","asArrayBuffer"],f=function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},l=0;l<h.length;l++)n.prototype[h[l]]=f;t.exports=n},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(e,f,t){(function(t){"use strict";var r,n,e=t.MutationObserver||t.WebKitMutationObserver;if(e){var i=0,s=new e(h),a=t.document.createTextNode("");s.observe(a,{characterData:!0}),r=function(){a.data=i=++i%2}}else if(t.setImmediate||void 0===t.MessageChannel)r="document"in t&&"onreadystatechange"in t.document.createElement("script")?function(){var e=t.document.createElement("script");e.onreadystatechange=function(){h(),e.onreadystatechange=null,e.parentNode.removeChild(e),e=null},t.document.documentElement.appendChild(e)}:function(){setTimeout(h,0)};else{var o=new t.MessageChannel;o.port1.onmessage=h,r=function(){o.port2.postMessage(0)}}var u=[];function h(){var e,t;n=!0;for(var r=u.length;r;){for(t=u,u=[],e=-1;++e<r;)t[e]();r=u.length}n=!1}f.exports=function(e){1!==u.push(e)||n||r()}}).call(this,void 0!==r?r:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],37:[function(e,t,r){"use strict";var i=e("immediate");function h(){}var f={},s=["REJECTED"],a=["FULFILLED"],n=["PENDING"];function o(e){if("function"!=typeof e)throw new TypeError("resolver must be a function");this.state=n,this.queue=[],this.outcome=void 0,e!==h&&c(this,e)}function u(e,t,r){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}function l(t,r,n){i(function(){var e;try{e=r(n)}catch(e){return f.reject(t,e)}e===t?f.reject(t,new TypeError("Cannot resolve promise with itself")):f.resolve(t,e)})}function d(e){var t=e&&e.then;if(e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof t)return function(){t.apply(e,arguments)}}function c(t,e){var r=!1;function n(e){r||(r=!0,f.reject(t,e))}function i(e){r||(r=!0,f.resolve(t,e))}var s=p(function(){e(i,n)});"error"===s.status&&n(s.value)}function p(e,t){var r={};try{r.value=e(t),r.status="success"}catch(e){r.status="error",r.value=e}return r}(t.exports=o).prototype.finally=function(t){if("function"!=typeof t)return this;var r=this.constructor;return this.then(function(e){return r.resolve(t()).then(function(){return e})},function(e){return r.resolve(t()).then(function(){throw e})})},o.prototype.catch=function(e){return this.then(null,e)},o.prototype.then=function(e,t){if("function"!=typeof e&&this.state===a||"function"!=typeof t&&this.state===s)return this;var r=new this.constructor(h);return this.state!==n?l(r,this.state===a?e:t,this.outcome):this.queue.push(new u(r,e,t)),r},u.prototype.callFulfilled=function(e){f.resolve(this.promise,e)},u.prototype.otherCallFulfilled=function(e){l(this.promise,this.onFulfilled,e)},u.prototype.callRejected=function(e){f.reject(this.promise,e)},u.prototype.otherCallRejected=function(e){l(this.promise,this.onRejected,e)},f.resolve=function(e,t){var r=p(d,t);if("error"===r.status)return f.reject(e,r.value);var n=r.value;if(n)c(e,n);else{e.state=a,e.outcome=t;for(var i=-1,s=e.queue.length;++i<s;)e.queue[i].callFulfilled(t)}return e},f.reject=function(e,t){e.state=s,e.outcome=t;for(var r=-1,n=e.queue.length;++r<n;)e.queue[r].callRejected(t);return e},o.resolve=function(e){return e instanceof this?e:f.resolve(new this(h),e)},o.reject=function(e){var t=new this(h);return f.reject(t,e)},o.all=function(e){var r=this;if("[object Array]"!==Object.prototype.toString.call(e))return this.reject(new TypeError("must be an array"));var n=e.length,i=!1;if(!n)return this.resolve([]);for(var s=new Array(n),a=0,t=-1,o=new this(h);++t<n;)u(e[t],t);return o;function u(e,t){r.resolve(e).then(function(e){s[t]=e,++a!==n||i||(i=!0,f.resolve(o,s))},function(e){i||(i=!0,f.reject(o,e))})}},o.race=function(e){if("[object Array]"!==Object.prototype.toString.call(e))return this.reject(new TypeError("must be an array"));var t=e.length,r=!1;if(!t)return this.resolve([]);for(var n,i=-1,s=new this(h);++i<t;)n=e[i],this.resolve(n).then(function(e){r||(r=!0,f.resolve(s,e))},function(e){r||(r=!0,f.reject(s,e))});return s}},{immediate:36}],38:[function(e,t,r){"use strict";var n={};(0,e("./lib/utils/common").assign)(n,e("./lib/deflate"),e("./lib/inflate"),e("./lib/zlib/constants")),t.exports=n},{"./lib/deflate":39,"./lib/inflate":40,"./lib/utils/common":41,"./lib/zlib/constants":44}],39:[function(e,t,r){"use strict";var a=e("./zlib/deflate"),o=e("./utils/common"),u=e("./utils/strings"),i=e("./zlib/messages"),s=e("./zlib/zstream"),h=Object.prototype.toString,f=0,l=-1,d=0,c=8;function p(e){if(!(this instanceof p))return new p(e);this.options=o.assign({level:l,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:d,to:""},e||{});var t=this.options;t.raw&&0<t.windowBits?t.windowBits=-t.windowBits:t.gzip&&0<t.windowBits&&t.windowBits<16&&(t.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new s,this.strm.avail_out=0;var r=a.deflateInit2(this.strm,t.level,t.method,t.windowBits,t.memLevel,t.strategy);if(r!==f)throw new Error(i[r]);if(t.header&&a.deflateSetHeader(this.strm,t.header),t.dictionary){var n;if(n="string"==typeof t.dictionary?u.string2buf(t.dictionary):"[object ArrayBuffer]"===h.call(t.dictionary)?new Uint8Array(t.dictionary):t.dictionary,(r=a.deflateSetDictionary(this.strm,n))!==f)throw new Error(i[r]);this._dict_set=!0}}function n(e,t){var r=new p(t);if(r.push(e,!0),r.err)throw r.msg||i[r.err];return r.result}p.prototype.push=function(e,t){var r,n,i=this.strm,s=this.options.chunkSize;if(this.ended)return!1;n=t===~~t?t:!0===t?4:0,"string"==typeof e?i.input=u.string2buf(e):"[object ArrayBuffer]"===h.call(e)?i.input=new Uint8Array(e):i.input=e,i.next_in=0,i.avail_in=i.input.length;do{if(0===i.avail_out&&(i.output=new o.Buf8(s),i.next_out=0,i.avail_out=s),1!==(r=a.deflate(i,n))&&r!==f)return this.onEnd(r),!(this.ended=!0);0!==i.avail_out&&(0!==i.avail_in||4!==n&&2!==n)||("string"===this.options.to?this.onData(u.buf2binstring(o.shrinkBuf(i.output,i.next_out))):this.onData(o.shrinkBuf(i.output,i.next_out)))}while((0<i.avail_in||0===i.avail_out)&&1!==r);return 4===n?(r=a.deflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===f):2!==n||(this.onEnd(f),!(i.avail_out=0))},p.prototype.onData=function(e){this.chunks.push(e)},p.prototype.onEnd=function(e){e===f&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=o.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},r.Deflate=p,r.deflate=n,r.deflateRaw=function(e,t){return(t=t||{}).raw=!0,n(e,t)},r.gzip=function(e,t){return(t=t||{}).gzip=!0,n(e,t)}},{"./utils/common":41,"./utils/strings":42,"./zlib/deflate":46,"./zlib/messages":51,"./zlib/zstream":53}],40:[function(e,t,r){"use strict";var d=e("./zlib/inflate"),c=e("./utils/common"),p=e("./utils/strings"),m=e("./zlib/constants"),n=e("./zlib/messages"),i=e("./zlib/zstream"),s=e("./zlib/gzheader"),_=Object.prototype.toString;function a(e){if(!(this instanceof a))return new a(e);this.options=c.assign({chunkSize:16384,windowBits:0,to:""},e||{});var t=this.options;t.raw&&0<=t.windowBits&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(0<=t.windowBits&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),15<t.windowBits&&t.windowBits<48&&0==(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new i,this.strm.avail_out=0;var r=d.inflateInit2(this.strm,t.windowBits);if(r!==m.Z_OK)throw new Error(n[r]);this.header=new s,d.inflateGetHeader(this.strm,this.header)}function o(e,t){var r=new a(t);if(r.push(e,!0),r.err)throw r.msg||n[r.err];return r.result}a.prototype.push=function(e,t){var r,n,i,s,a,o,u=this.strm,h=this.options.chunkSize,f=this.options.dictionary,l=!1;if(this.ended)return!1;n=t===~~t?t:!0===t?m.Z_FINISH:m.Z_NO_FLUSH,"string"==typeof e?u.input=p.binstring2buf(e):"[object ArrayBuffer]"===_.call(e)?u.input=new Uint8Array(e):u.input=e,u.next_in=0,u.avail_in=u.input.length;do{if(0===u.avail_out&&(u.output=new c.Buf8(h),u.next_out=0,u.avail_out=h),(r=d.inflate(u,m.Z_NO_FLUSH))===m.Z_NEED_DICT&&f&&(o="string"==typeof f?p.string2buf(f):"[object ArrayBuffer]"===_.call(f)?new Uint8Array(f):f,r=d.inflateSetDictionary(this.strm,o)),r===m.Z_BUF_ERROR&&!0===l&&(r=m.Z_OK,l=!1),r!==m.Z_STREAM_END&&r!==m.Z_OK)return this.onEnd(r),!(this.ended=!0);u.next_out&&(0!==u.avail_out&&r!==m.Z_STREAM_END&&(0!==u.avail_in||n!==m.Z_FINISH&&n!==m.Z_SYNC_FLUSH)||("string"===this.options.to?(i=p.utf8border(u.output,u.next_out),s=u.next_out-i,a=p.buf2string(u.output,i),u.next_out=s,u.avail_out=h-s,s&&c.arraySet(u.output,u.output,i,s,0),this.onData(a)):this.onData(c.shrinkBuf(u.output,u.next_out)))),0===u.avail_in&&0===u.avail_out&&(l=!0)}while((0<u.avail_in||0===u.avail_out)&&r!==m.Z_STREAM_END);return r===m.Z_STREAM_END&&(n=m.Z_FINISH),n===m.Z_FINISH?(r=d.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===m.Z_OK):n!==m.Z_SYNC_FLUSH||(this.onEnd(m.Z_OK),!(u.avail_out=0))},a.prototype.onData=function(e){this.chunks.push(e)},a.prototype.onEnd=function(e){e===m.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=c.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},r.Inflate=a,r.inflate=o,r.inflateRaw=function(e,t){return(t=t||{}).raw=!0,o(e,t)},r.ungzip=o},{"./utils/common":41,"./utils/strings":42,"./zlib/constants":44,"./zlib/gzheader":47,"./zlib/inflate":49,"./zlib/messages":51,"./zlib/zstream":53}],41:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;r.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var r=t.shift();if(r){if("object"!=typeof r)throw new TypeError(r+"must be non-object");for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}}return e},r.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var i={arraySet:function(e,t,r,n,i){if(t.subarray&&e.subarray)e.set(t.subarray(r,r+n),i);else for(var s=0;s<n;s++)e[i+s]=t[r+s]},flattenChunks:function(e){var t,r,n,i,s,a;for(t=n=0,r=e.length;t<r;t++)n+=e[t].length;for(a=new Uint8Array(n),t=i=0,r=e.length;t<r;t++)s=e[t],a.set(s,i),i+=s.length;return a}},s={arraySet:function(e,t,r,n,i){for(var s=0;s<n;s++)e[i+s]=t[r+s]},flattenChunks:function(e){return[].concat.apply([],e)}};r.setTyped=function(e){e?(r.Buf8=Uint8Array,r.Buf16=Uint16Array,r.Buf32=Int32Array,r.assign(r,i)):(r.Buf8=Array,r.Buf16=Array,r.Buf32=Array,r.assign(r,s))},r.setTyped(n)},{}],42:[function(e,t,r){"use strict";var u=e("./common"),i=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(e){i=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(e){s=!1}for(var h=new u.Buf8(256),n=0;n<256;n++)h[n]=252<=n?6:248<=n?5:240<=n?4:224<=n?3:192<=n?2:1;function f(e,t){if(t<65537&&(e.subarray&&s||!e.subarray&&i))return String.fromCharCode.apply(null,u.shrinkBuf(e,t));for(var r="",n=0;n<t;n++)r+=String.fromCharCode(e[n]);return r}h[254]=h[254]=1,r.string2buf=function(e){var t,r,n,i,s,a=e.length,o=0;for(i=0;i<a;i++)55296==(64512&(r=e.charCodeAt(i)))&&i+1<a&&56320==(64512&(n=e.charCodeAt(i+1)))&&(r=65536+(r-55296<<10)+(n-56320),i++),o+=r<128?1:r<2048?2:r<65536?3:4;for(t=new u.Buf8(o),i=s=0;s<o;i++)55296==(64512&(r=e.charCodeAt(i)))&&i+1<a&&56320==(64512&(n=e.charCodeAt(i+1)))&&(r=65536+(r-55296<<10)+(n-56320),i++),r<128?t[s++]=r:(r<2048?t[s++]=192|r>>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t},r.buf2binstring=function(e){return f(e,e.length)},r.binstring2buf=function(e){for(var t=new u.Buf8(e.length),r=0,n=t.length;r<n;r++)t[r]=e.charCodeAt(r);return t},r.buf2string=function(e,t){var r,n,i,s,a=t||e.length,o=new Array(2*a);for(r=n=0;r<a;)if((i=e[r++])<128)o[n++]=i;else if(4<(s=h[i]))o[n++]=65533,r+=s-1;else{for(i&=2===s?31:3===s?15:7;1<s&&r<a;)i=i<<6|63&e[r++],s--;1<s?o[n++]=65533:i<65536?o[n++]=i:(i-=65536,o[n++]=55296|i>>10&1023,o[n++]=56320|1023&i)}return f(o,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+h[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e|0,s=e>>>16&65535|0,a=0;0!==r;){for(r-=a=2e3<r?2e3:r;s=s+(i=i+t[n++]|0)|0,--a;);i%=65521,s%=65521}return i|s<<16|0}},{}],44:[function(e,t,r){"use strict";t.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],45:[function(e,t,r){"use strict";var o=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a<s;a++)e=e>>>8^i[255&(e^t[a])];return-1^e}},{}],46:[function(e,t,r){"use strict";var u,d=e("../utils/common"),h=e("./trees"),c=e("./adler32"),p=e("./crc32"),n=e("./messages"),f=0,l=0,m=-2,i=2,_=8,s=286,a=30,o=19,g=2*s+1,v=15,b=3,w=258,y=w+b+1,k=42,x=113;function S(e,t){return e.msg=n[t],t}function z(e){return(e<<1)-(4<e?9:0)}function E(e){for(var t=e.length;0<=--t;)e[t]=0}function C(e){var t=e.state,r=t.pending;r>e.avail_out&&(r=e.avail_out),0!==r&&(d.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function A(e,t){h._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,C(e.strm)}function I(e,t){e.pending_buf[e.pending++]=t}function O(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function B(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,u=e.strstart>e.w_size-y?e.strstart-(e.w_size-y):0,h=e.window,f=e.w_mask,l=e.prev,d=e.strstart+w,c=h[s+a-1],p=h[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(h[(r=t)+a]===p&&h[r+a-1]===c&&h[r]===h[s]&&h[++r]===h[s+1]){s+=2,r++;do{}while(h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&h[++s]===h[++r]&&s<d);if(n=w-(d-s),s=d-w,a<n){if(e.match_start=t,o<=(a=n))break;c=h[s+a-1],p=h[s+a]}}}while((t=l[t&f])>u&&0!=--i);return a<=e.lookahead?a:e.lookahead}function T(e){var t,r,n,i,s,a,o,u,h,f,l=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=l+(l-y)){for(d.arraySet(e.window,e.window,l,l,0),e.match_start-=l,e.strstart-=l,e.block_start-=l,t=r=e.hash_size;n=e.head[--t],e.head[t]=l<=n?n-l:0,--r;);for(t=r=l;n=e.prev[--t],e.prev[t]=l<=n?n-l:0,--r;);i+=l}if(0===e.strm.avail_in)break;if(a=e.strm,o=e.window,u=e.strstart+e.lookahead,f=void 0,(h=i)<(f=a.avail_in)&&(f=h),r=0===f?0:(a.avail_in-=f,d.arraySet(o,a.input,a.next_in,f,u),1===a.state.wrap?a.adler=c(a.adler,o,f,u):2===a.state.wrap&&(a.adler=p(a.adler,o,f,u)),a.next_in+=f,a.total_in+=f,f),e.lookahead+=r,e.lookahead+e.insert>=b)for(s=e.strstart-e.insert,e.ins_h=e.window[s],e.ins_h=(e.ins_h<<e.hash_shift^e.window[s+1])&e.hash_mask;e.insert&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[s+b-1])&e.hash_mask,e.prev[s&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=s,s++,e.insert--,!(e.lookahead+e.insert<b)););}while(e.lookahead<y&&0!==e.strm.avail_in)}function R(e,t){for(var r,n;;){if(e.lookahead<y){if(T(e),e.lookahead<y&&t===f)return 1;if(0===e.lookahead)break}if(r=0,e.lookahead>=b&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+b-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!==r&&e.strstart-r<=e.w_size-y&&(e.match_length=B(e,r)),e.match_length>=b)if(n=h._tr_tally(e,e.strstart-e.match_start,e.match_length-b),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=b){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+b-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart,0!=--e.match_length;);e.strstart++}else e.strstart+=e.match_length,e.match_length=0,e.ins_h=e.window[e.strstart],e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+1])&e.hash_mask;else n=h._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++;if(n&&(A(e,!1),0===e.strm.avail_out))return 1}return e.insert=e.strstart<b-1?e.strstart:b-1,4===t?(A(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(A(e,!1),0===e.strm.avail_out)?1:2}function D(e,t){for(var r,n,i;;){if(e.lookahead<y){if(T(e),e.lookahead<y&&t===f)return 1;if(0===e.lookahead)break}if(r=0,e.lookahead>=b&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+b-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),e.prev_length=e.match_length,e.prev_match=e.match_start,e.match_length=b-1,0!==r&&e.prev_length<e.max_lazy_match&&e.strstart-r<=e.w_size-y&&(e.match_length=B(e,r),e.match_length<=5&&(1===e.strategy||e.match_length===b&&4096<e.strstart-e.match_start)&&(e.match_length=b-1)),e.prev_length>=b&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-b,n=h._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-b),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+b-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!=--e.prev_length;);if(e.match_available=0,e.match_length=b-1,e.strstart++,n&&(A(e,!1),0===e.strm.avail_out))return 1}else if(e.match_available){if((n=h._tr_tally(e,0,e.window[e.strstart-1]))&&A(e,!1),e.strstart++,e.lookahead--,0===e.strm.avail_out)return 1}else e.match_available=1,e.strstart++,e.lookahead--}return e.match_available&&(n=h._tr_tally(e,0,e.window[e.strstart-1]),e.match_available=0),e.insert=e.strstart<b-1?e.strstart:b-1,4===t?(A(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(A(e,!1),0===e.strm.avail_out)?1:2}function F(e,t,r,n,i){this.good_length=e,this.max_lazy=t,this.nice_length=r,this.max_chain=n,this.func=i}function N(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=_,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new d.Buf16(2*g),this.dyn_dtree=new d.Buf16(2*(2*a+1)),this.bl_tree=new d.Buf16(2*(2*o+1)),E(this.dyn_ltree),E(this.dyn_dtree),E(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new d.Buf16(v+1),this.heap=new d.Buf16(2*s+1),E(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new d.Buf16(2*s+1),E(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function U(e){var t;return e&&e.state?(e.total_in=e.total_out=0,e.data_type=i,(t=e.state).pending=0,t.pending_out=0,t.wrap<0&&(t.wrap=-t.wrap),t.status=t.wrap?k:x,e.adler=2===t.wrap?0:1,t.last_flush=f,h._tr_init(t),l):S(e,m)}function P(e){var t,r=U(e);return r===l&&((t=e.state).window_size=2*t.w_size,E(t.head),t.max_lazy_match=u[t.level].max_lazy,t.good_match=u[t.level].good_length,t.nice_match=u[t.level].nice_length,t.max_chain_length=u[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=b-1,t.match_available=0,t.ins_h=0),r}function L(e,t,r,n,i,s){if(!e)return m;var a=1;if(-1===t&&(t=6),n<0?(a=0,n=-n):15<n&&(a=2,n-=16),i<1||9<i||r!==_||n<8||15<n||t<0||9<t||s<0||4<s)return S(e,m);8===n&&(n=9);var o=new N;return(e.state=o).strm=e,o.wrap=a,o.gzhead=null,o.w_bits=n,o.w_size=1<<o.w_bits,o.w_mask=o.w_size-1,o.hash_bits=i+7,o.hash_size=1<<o.hash_bits,o.hash_mask=o.hash_size-1,o.hash_shift=~~((o.hash_bits+b-1)/b),o.window=new d.Buf8(2*o.w_size),o.head=new d.Buf16(o.hash_size),o.prev=new d.Buf16(o.w_size),o.lit_bufsize=1<<i+6,o.pending_buf_size=4*o.lit_bufsize,o.pending_buf=new d.Buf8(o.pending_buf_size),o.d_buf=1*o.lit_bufsize,o.l_buf=3*o.lit_bufsize,o.level=t,o.strategy=s,o.method=r,P(e)}u=[new F(0,0,0,0,function(e,t){var r=65535;for(r>e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(T(e),0===e.lookahead&&t===f)return 1;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,A(e,!1),0===e.strm.avail_out))return 1;if(e.strstart-e.block_start>=e.w_size-y&&(A(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(A(e,!0),0===e.strm.avail_out?3:4):(e.strstart>e.block_start&&(A(e,!1),e.strm.avail_out),1)}),new F(4,4,8,4,R),new F(4,5,16,8,R),new F(4,6,32,32,R),new F(4,4,16,16,D),new F(8,16,32,32,D),new F(8,16,128,128,D),new F(8,32,128,256,D),new F(32,128,258,1024,D),new F(32,258,258,4096,D)],r.deflateInit=function(e,t){return L(e,t,_,15,8,0)},r.deflateInit2=L,r.deflateReset=P,r.deflateResetKeep=U,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?m:(e.state.gzhead=t,l):m},r.deflate=function(e,t){var r,n,i,s;if(!e||!e.state||5<t||t<0)return e?S(e,m):m;if(n=e.state,!e.output||!e.input&&0!==e.avail_in||666===n.status&&4!==t)return S(e,0===e.avail_out?-5:m);if(n.strm=e,r=n.last_flush,n.last_flush=t,n.status===k)if(2===n.wrap)e.adler=0,I(n,31),I(n,139),I(n,8),n.gzhead?(I(n,(n.gzhead.text?1:0)+(n.gzhead.hcrc?2:0)+(n.gzhead.extra?4:0)+(n.gzhead.name?8:0)+(n.gzhead.comment?16:0)),I(n,255&n.gzhead.time),I(n,n.gzhead.time>>8&255),I(n,n.gzhead.time>>16&255),I(n,n.gzhead.time>>24&255),I(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),I(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(I(n,255&n.gzhead.extra.length),I(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=p(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=69):(I(n,0),I(n,0),I(n,0),I(n,0),I(n,0),I(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),I(n,3),n.status=x);else{var a=_+(n.w_bits-8<<4)<<8;a|=(2<=n.strategy||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=32),a+=31-a%31,n.status=x,O(n,a),0!==n.strstart&&(O(n,e.adler>>>16),O(n,65535&e.adler)),e.adler=1}if(69===n.status)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),C(e),i=n.pending,n.pending!==n.pending_buf_size));)I(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=73)}else n.status=73;if(73===n.status)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),C(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindex<n.gzhead.name.length?255&n.gzhead.name.charCodeAt(n.gzindex++):0,I(n,s)}while(0!==s);n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.gzindex=0,n.status=91)}else n.status=91;if(91===n.status)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),C(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindex<n.gzhead.comment.length?255&n.gzhead.comment.charCodeAt(n.gzindex++):0,I(n,s)}while(0!==s);n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.status=103)}else n.status=103;if(103===n.status&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&C(e),n.pending+2<=n.pending_buf_size&&(I(n,255&e.adler),I(n,e.adler>>8&255),e.adler=0,n.status=x)):n.status=x),0!==n.pending){if(C(e),0===e.avail_out)return n.last_flush=-1,l}else if(0===e.avail_in&&z(t)<=z(r)&&4!==t)return S(e,-5);if(666===n.status&&0!==e.avail_in)return S(e,-5);if(0!==e.avail_in||0!==n.lookahead||t!==f&&666!==n.status){var o=2===n.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(T(e),0===e.lookahead)){if(t===f)return 1;break}if(e.match_length=0,r=h._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(A(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(A(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(A(e,!1),0===e.strm.avail_out)?1:2}(n,t):3===n.strategy?function(e,t){for(var r,n,i,s,a=e.window;;){if(e.lookahead<=w){if(T(e),e.lookahead<=w&&t===f)return 1;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=b&&0<e.strstart&&(n=a[i=e.strstart-1])===a[++i]&&n===a[++i]&&n===a[++i]){s=e.strstart+w;do{}while(n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&i<s);e.match_length=w-(s-i),e.match_length>e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=b?(r=h._tr_tally(e,1,e.match_length-b),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=h._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(A(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(A(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(A(e,!1),0===e.strm.avail_out)?1:2}(n,t):u[n.level].func(n,t);if(3!==o&&4!==o||(n.status=666),1===o||3===o)return 0===e.avail_out&&(n.last_flush=-1),l;if(2===o&&(1===t?h._tr_align(n):5!==t&&(h._tr_stored_block(n,0,0,!1),3===t&&(E(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),C(e),0===e.avail_out))return n.last_flush=-1,l}return 4!==t?l:n.wrap<=0?1:(2===n.wrap?(I(n,255&e.adler),I(n,e.adler>>8&255),I(n,e.adler>>16&255),I(n,e.adler>>24&255),I(n,255&e.total_in),I(n,e.total_in>>8&255),I(n,e.total_in>>16&255),I(n,e.total_in>>24&255)):(O(n,e.adler>>>16),O(n,65535&e.adler)),C(e),0<n.wrap&&(n.wrap=-n.wrap),0!==n.pending?l:1)},r.deflateEnd=function(e){var t;return e&&e.state?(t=e.state.status)!==k&&69!==t&&73!==t&&91!==t&&103!==t&&t!==x&&666!==t?S(e,m):(e.state=null,t===x?S(e,-3):l):m},r.deflateSetDictionary=function(e,t){var r,n,i,s,a,o,u,h,f=t.length;if(!e||!e.state)return m;if(2===(s=(r=e.state).wrap)||1===s&&r.status!==k||r.lookahead)return m;for(1===s&&(e.adler=c(e.adler,t,f,0)),r.wrap=0,f>=r.w_size&&(0===s&&(E(r.head),r.strstart=0,r.block_start=0,r.insert=0),h=new d.Buf8(r.w_size),d.arraySet(h,t,f-r.w_size,r.w_size,0),t=h,f=r.w_size),a=e.avail_in,o=e.next_in,u=e.input,e.avail_in=f,e.next_in=0,e.input=t,T(r);r.lookahead>=b;){for(n=r.strstart,i=r.lookahead-(b-1);r.ins_h=(r.ins_h<<r.hash_shift^r.window[n+b-1])&r.hash_mask,r.prev[n&r.w_mask]=r.head[r.ins_h],r.head[r.ins_h]=n,n++,--i;);r.strstart=n,r.lookahead=b-1,T(r)}return r.strstart+=r.lookahead,r.block_start=r.strstart,r.insert=r.lookahead,r.lookahead=0,r.match_length=r.prev_length=b-1,r.match_available=0,e.next_in=o,e.input=u,e.avail_in=a,r.wrap=s,l},r.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./messages":51,"./trees":52}],47:[function(e,t,r){"use strict";t.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],48:[function(e,t,r){"use strict";t.exports=function(e,t){var r,n,i,s,a,o,u,h,f,l,d,c,p,m,_,g,v,b,w,y,k,x,S,z,E;r=e.state,n=e.next_in,z=e.input,i=n+(e.avail_in-5),s=e.next_out,E=e.output,a=s-(t-e.avail_out),o=s+(e.avail_out-257),u=r.dmax,h=r.wsize,f=r.whave,l=r.wnext,d=r.window,c=r.hold,p=r.bits,m=r.lencode,_=r.distcode,g=(1<<r.lenbits)-1,v=(1<<r.distbits)-1;e:do{p<15&&(c+=z[n++]<<p,p+=8,c+=z[n++]<<p,p+=8),b=m[c&g];t:for(;;){if(c>>>=w=b>>>24,p-=w,0==(w=b>>>16&255))E[s++]=65535&b;else{if(!(16&w)){if(0==(64&w)){b=m[(65535&b)+(c&(1<<w)-1)];continue t}if(32&w){r.mode=12;break e}e.msg="invalid literal/length code",r.mode=30;break e}y=65535&b,(w&=15)&&(p<w&&(c+=z[n++]<<p,p+=8),y+=c&(1<<w)-1,c>>>=w,p-=w),p<15&&(c+=z[n++]<<p,p+=8,c+=z[n++]<<p,p+=8),b=_[c&v];r:for(;;){if(c>>>=w=b>>>24,p-=w,!(16&(w=b>>>16&255))){if(0==(64&w)){b=_[(65535&b)+(c&(1<<w)-1)];continue r}e.msg="invalid distance code",r.mode=30;break e}if(k=65535&b,p<(w&=15)&&(c+=z[n++]<<p,(p+=8)<w&&(c+=z[n++]<<p,p+=8)),u<(k+=c&(1<<w)-1)){e.msg="invalid distance too far back",r.mode=30;break e}if(c>>>=w,p-=w,(w=s-a)<k){if(f<(w=k-w)&&r.sane){e.msg="invalid distance too far back",r.mode=30;break e}if(S=d,(x=0)===l){if(x+=h-w,w<y){for(y-=w;E[s++]=d[x++],--w;);x=s-k,S=E}}else if(l<w){if(x+=h+l-w,(w-=l)<y){for(y-=w;E[s++]=d[x++],--w;);if(x=0,l<y){for(y-=w=l;E[s++]=d[x++],--w;);x=s-k,S=E}}}else if(x+=l-w,w<y){for(y-=w;E[s++]=d[x++],--w;);x=s-k,S=E}for(;2<y;)E[s++]=S[x++],E[s++]=S[x++],E[s++]=S[x++],y-=3;y&&(E[s++]=S[x++],1<y&&(E[s++]=S[x++]))}else{for(x=s-k;E[s++]=E[x++],E[s++]=E[x++],E[s++]=E[x++],2<(y-=3););y&&(E[s++]=E[x++],1<y&&(E[s++]=E[x++]))}break}}break}}while(n<i&&s<o);n-=y=p>>3,c&=(1<<(p-=y<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n<i?i-n+5:5-(n-i),e.avail_out=s<o?o-s+257:257-(s-o),r.hold=c,r.bits=p}},{}],49:[function(e,t,r){"use strict";var I=e("../utils/common"),O=e("./adler32"),B=e("./crc32"),T=e("./inffast"),R=e("./inftrees"),D=1,F=2,N=0,U=-2,P=1,n=852,i=592;function L(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function s(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=P,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new I.Buf32(n),t.distcode=t.distdyn=new I.Buf32(i),t.sane=1,t.back=-1,N):U}function o(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,a(e)):U}function u(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15<t)?U:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=r,n.wbits=t,o(e))):U}function h(e,t){var r,n;return e?(n=new s,(e.state=n).window=null,(r=u(e,t))!==N&&(e.state=null),r):U}var f,l,d=!0;function j(e){if(d){var t;for(f=new I.Buf32(512),l=new I.Buf32(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(R(D,e.lens,0,288,f,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;R(F,e.lens,0,32,l,0,e.work,{bits:5}),d=!1}e.lencode=f,e.lenbits=9,e.distcode=l,e.distbits=5}function Z(e,t,r,n){var i,s=e.state;return null===s.window&&(s.wsize=1<<s.wbits,s.wnext=0,s.whave=0,s.window=new I.Buf8(s.wsize)),n>=s.wsize?(I.arraySet(s.window,t,r-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(n<(i=s.wsize-s.wnext)&&(i=n),I.arraySet(s.window,t,r-n,i,s.wnext),(n-=i)?(I.arraySet(s.window,t,r-n,n,0),s.wnext=n,s.whave=s.wsize):(s.wnext+=i,s.wnext===s.wsize&&(s.wnext=0),s.whave<s.wsize&&(s.whave+=i))),0}r.inflateReset=o,r.inflateReset2=u,r.inflateResetKeep=a,r.inflateInit=function(e){return h(e,15)},r.inflateInit2=h,r.inflate=function(e,t){var r,n,i,s,a,o,u,h,f,l,d,c,p,m,_,g,v,b,w,y,k,x,S,z,E=0,C=new I.Buf8(4),A=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!e||!e.state||!e.output||!e.input&&0!==e.avail_in)return U;12===(r=e.state).mode&&(r.mode=13),a=e.next_out,i=e.output,u=e.avail_out,s=e.next_in,n=e.input,o=e.avail_in,h=r.hold,f=r.bits,l=o,d=u,x=N;e:for(;;)switch(r.mode){case P:if(0===r.wrap){r.mode=13;break}for(;f<16;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(2&r.wrap&&35615===h){C[r.check=0]=255&h,C[1]=h>>>8&255,r.check=B(r.check,C,2,0),f=h=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&h)<<8)+(h>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&h)){e.msg="unknown compression method",r.mode=30;break}if(f-=4,k=8+(15&(h>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<<k,e.adler=r.check=1,r.mode=512&h?10:12,f=h=0;break;case 2:for(;f<16;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(r.flags=h,8!=(255&r.flags)){e.msg="unknown compression method",r.mode=30;break}if(57344&r.flags){e.msg="unknown header flags set",r.mode=30;break}r.head&&(r.head.text=h>>8&1),512&r.flags&&(C[0]=255&h,C[1]=h>>>8&255,r.check=B(r.check,C,2,0)),f=h=0,r.mode=3;case 3:for(;f<32;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.head&&(r.head.time=h),512&r.flags&&(C[0]=255&h,C[1]=h>>>8&255,C[2]=h>>>16&255,C[3]=h>>>24&255,r.check=B(r.check,C,4,0)),f=h=0,r.mode=4;case 4:for(;f<16;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.head&&(r.head.xflags=255&h,r.head.os=h>>8),512&r.flags&&(C[0]=255&h,C[1]=h>>>8&255,r.check=B(r.check,C,2,0)),f=h=0,r.mode=5;case 5:if(1024&r.flags){for(;f<16;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.length=h,r.head&&(r.head.extra_len=h),512&r.flags&&(C[0]=255&h,C[1]=h>>>8&255,r.check=B(r.check,C,2,0)),f=h=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(o<(c=r.length)&&(c=o),c&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,n,s,c,k)),512&r.flags&&(r.check=B(r.check,n,c,s)),o-=c,s+=c,r.length-=c),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===o)break e;for(c=0;k=n[s+c++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&c<o;);if(512&r.flags&&(r.check=B(r.check,n,c,s)),o-=c,s+=c,k)break e}else r.head&&(r.head.name=null);r.length=0,r.mode=8;case 8:if(4096&r.flags){if(0===o)break e;for(c=0;k=n[s+c++],r.head&&k&&r.length<65536&&(r.head.comment+=String.fromCharCode(k)),k&&c<o;);if(512&r.flags&&(r.check=B(r.check,n,c,s)),o-=c,s+=c,k)break e}else r.head&&(r.head.comment=null);r.mode=9;case 9:if(512&r.flags){for(;f<16;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(h!==(65535&r.check)){e.msg="header crc mismatch",r.mode=30;break}f=h=0}r.head&&(r.head.hcrc=r.flags>>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;f<32;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}e.adler=r.check=L(h),f=h=0,r.mode=11;case 11:if(0===r.havedict)return e.next_out=a,e.avail_out=u,e.next_in=s,e.avail_in=o,r.hold=h,r.bits=f,2;e.adler=r.check=1,r.mode=12;case 12:if(5===t||6===t)break e;case 13:if(r.last){h>>>=7&f,f-=7&f,r.mode=27;break}for(;f<3;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}switch(r.last=1&h,f-=1,3&(h>>>=1)){case 0:r.mode=14;break;case 1:if(j(r),r.mode=20,6!==t)break;h>>>=2,f-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}h>>>=2,f-=2;break;case 14:for(h>>>=7&f,f-=7&f;f<32;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if((65535&h)!=(h>>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&h,f=h=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(c=r.length){if(o<c&&(c=o),u<c&&(c=u),0===c)break e;I.arraySet(i,n,s,c,a),o-=c,s+=c,u-=c,a+=c,r.length-=c;break}r.mode=12;break;case 17:for(;f<14;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(r.nlen=257+(31&h),h>>>=5,f-=5,r.ndist=1+(31&h),h>>>=5,f-=5,r.ncode=4+(15&h),h>>>=4,f-=4,286<r.nlen||30<r.ndist){e.msg="too many length or distance symbols",r.mode=30;break}r.have=0,r.mode=18;case 18:for(;r.have<r.ncode;){for(;f<3;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.lens[A[r.have++]]=7&h,h>>>=3,f-=3}for(;r.have<19;)r.lens[A[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=R(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have<r.nlen+r.ndist;){for(;g=(E=r.lencode[h&(1<<r.lenbits)-1])>>>16&255,v=65535&E,!((_=E>>>24)<=f);){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(v<16)h>>>=_,f-=_,r.lens[r.have++]=v;else{if(16===v){for(z=_+2;f<z;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(h>>>=_,f-=_,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],c=3+(3&h),h>>>=2,f-=2}else if(17===v){for(z=_+3;f<z;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}f-=_,k=0,c=3+(7&(h>>>=_)),h>>>=3,f-=3}else{for(z=_+7;f<z;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}f-=_,k=0,c=11+(127&(h>>>=_)),h>>>=7,f-=7}if(r.have+c>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;c--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=R(D,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=R(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=o&&258<=u){e.next_out=a,e.avail_out=u,e.next_in=s,e.avail_in=o,r.hold=h,r.bits=f,T(e,d),a=e.next_out,i=e.output,u=e.avail_out,s=e.next_in,n=e.input,o=e.avail_in,h=r.hold,f=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;g=(E=r.lencode[h&(1<<r.lenbits)-1])>>>16&255,v=65535&E,!((_=E>>>24)<=f);){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(g&&0==(240&g)){for(b=_,w=g,y=v;g=(E=r.lencode[y+((h&(1<<b+w)-1)>>b)])>>>16&255,v=65535&E,!(b+(_=E>>>24)<=f);){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}h>>>=b,f-=b,r.back+=b}if(h>>>=_,f-=_,r.back+=_,r.length=v,0===g){r.mode=26;break}if(32&g){r.back=-1,r.mode=12;break}if(64&g){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&g,r.mode=22;case 22:if(r.extra){for(z=r.extra;f<z;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.length+=h&(1<<r.extra)-1,h>>>=r.extra,f-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;g=(E=r.distcode[h&(1<<r.distbits)-1])>>>16&255,v=65535&E,!((_=E>>>24)<=f);){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(0==(240&g)){for(b=_,w=g,y=v;g=(E=r.distcode[y+((h&(1<<b+w)-1)>>b)])>>>16&255,v=65535&E,!(b+(_=E>>>24)<=f);){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}h>>>=b,f-=b,r.back+=b}if(h>>>=_,f-=_,r.back+=_,64&g){e.msg="invalid distance code",r.mode=30;break}r.offset=v,r.extra=15&g,r.mode=24;case 24:if(r.extra){for(z=r.extra;f<z;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}r.offset+=h&(1<<r.extra)-1,h>>>=r.extra,f-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===u)break e;if(c=d-u,r.offset>c){if((c=r.offset-c)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}p=c>r.wnext?(c-=r.wnext,r.wsize-c):r.wnext-c,c>r.length&&(c=r.length),m=r.window}else m=i,p=a-r.offset,c=r.length;for(u<c&&(c=u),u-=c,r.length-=c;i[a++]=m[p++],--c;);0===r.length&&(r.mode=21);break;case 26:if(0===u)break e;i[a++]=r.length,u--,r.mode=21;break;case 27:if(r.wrap){for(;f<32;){if(0===o)break e;o--,h|=n[s++]<<f,f+=8}if(d-=u,e.total_out+=d,r.total+=d,d&&(e.adler=r.check=r.flags?B(r.check,i,d,a-d):O(r.check,i,d,a-d)),d=u,(r.flags?h:L(h))!==r.check){e.msg="incorrect data check",r.mode=30;break}f=h=0}r.mode=28;case 28:if(r.wrap&&r.flags){for(;f<32;){if(0===o)break e;o--,h+=n[s++]<<f,f+=8}if(h!==(4294967295&r.total)){e.msg="incorrect length check",r.mode=30;break}f=h=0}r.mode=29;case 29:x=1;break e;case 30:x=-3;break e;case 31:return-4;case 32:default:return U}return e.next_out=a,e.avail_out=u,e.next_in=s,e.avail_in=o,r.hold=h,r.bits=f,(r.wsize||d!==e.avail_out&&r.mode<30&&(r.mode<27||4!==t))&&Z(e,e.output,e.next_out,d-e.avail_out)?(r.mode=31,-4):(l-=e.avail_in,d-=e.avail_out,e.total_in+=l,e.total_out+=d,r.total+=d,r.wrap&&d&&(e.adler=r.check=r.flags?B(r.check,i,d,e.next_out-d):O(r.check,i,d,e.next_out-d)),e.data_type=r.bits+(r.last?64:0)+(12===r.mode?128:0)+(20===r.mode||15===r.mode?256:0),(0==l&&0===d||4===t)&&x===N&&(x=-5),x)},r.inflateEnd=function(e){if(!e||!e.state)return U;var t=e.state;return t.window&&(t.window=null),e.state=null,N},r.inflateGetHeader=function(e,t){var r;return e&&e.state?0==(2&(r=e.state).wrap)?U:((r.head=t).done=!1,N):U},r.inflateSetDictionary=function(e,t){var r,n=t.length;return e&&e.state?0!==(r=e.state).wrap&&11!==r.mode?U:11===r.mode&&O(1,t,n,0)!==r.check?-3:Z(e,t,n,n)?(r.mode=31,-4):(r.havedict=1,N):U},r.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./inffast":48,"./inftrees":50}],50:[function(e,t,r){"use strict";var D=e("../utils/common"),F=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],N=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],U=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],P=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];t.exports=function(e,t,r,n,i,s,a,o){var u,h,f,l,d,c,p,m,_,g=o.bits,v=0,b=0,w=0,y=0,k=0,x=0,S=0,z=0,E=0,C=0,A=null,I=0,O=new D.Buf16(16),B=new D.Buf16(16),T=null,R=0;for(v=0;v<=15;v++)O[v]=0;for(b=0;b<n;b++)O[t[r+b]]++;for(k=g,y=15;1<=y&&0===O[y];y--);if(y<k&&(k=y),0===y)return i[s++]=20971520,i[s++]=20971520,o.bits=1,0;for(w=1;w<y&&0===O[w];w++);for(k<w&&(k=w),v=z=1;v<=15;v++)if(z<<=1,(z-=O[v])<0)return-1;if(0<z&&(0===e||1!==y))return-1;for(B[1]=0,v=1;v<15;v++)B[v+1]=B[v]+O[v];for(b=0;b<n;b++)0!==t[r+b]&&(a[B[t[r+b]]++]=b);if(c=0===e?(A=T=a,19):1===e?(A=F,I-=257,T=N,R-=257,256):(A=U,T=P,-1),v=w,d=s,S=b=C=0,f=-1,l=(E=1<<(x=k))-1,1===e&&852<E||2===e&&592<E)return 1;for(;;){for(p=v-S,_=a[b]<c?(m=0,a[b]):a[b]>c?(m=T[R+a[b]],A[I+a[b]]):(m=96,0),u=1<<v-S,w=h=1<<x;i[d+(C>>S)+(h-=u)]=p<<24|m<<16|_|0,0!==h;);for(u=1<<v-1;C&u;)u>>=1;if(0!==u?(C&=u-1,C+=u):C=0,b++,0==--O[v]){if(v===y)break;v=t[r+a[b]]}if(k<v&&(C&l)!==f){for(0===S&&(S=k),d+=w,z=1<<(x=v-S);x+S<y&&!((z-=O[x+S])<=0);)x++,z<<=1;if(E+=1<<x,1===e&&852<E||2===e&&592<E)return 1;i[f=C&l]=k<<24|x<<16|d-s|0}}return 0!==C&&(i[d+C]=v-S<<24|64<<16|0),o.bits=k,0}},{"../utils/common":41}],51:[function(e,t,r){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],52:[function(e,t,r){"use strict";var o=e("../utils/common");function n(e){for(var t=e.length;0<=--t;)e[t]=0}var _=15,i=16,u=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],h=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],f=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],l=new Array(576);n(l);var d=new Array(60);n(d);var c=new Array(512);n(c);var p=new Array(256);n(p);var m=new Array(29);n(m);var g,v,b,w=new Array(30);function y(e,t,r,n,i){this.static_tree=e,this.extra_bits=t,this.extra_base=r,this.elems=n,this.max_length=i,this.has_stree=e&&e.length}function s(e,t){this.dyn_tree=e,this.max_code=0,this.stat_desc=t}function k(e){return e<256?c[e]:c[256+(e>>>7)]}function x(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function S(e,t,r){e.bi_valid>i-r?(e.bi_buf|=t<<e.bi_valid&65535,x(e,e.bi_buf),e.bi_buf=t>>i-e.bi_valid,e.bi_valid+=r-i):(e.bi_buf|=t<<e.bi_valid&65535,e.bi_valid+=r)}function z(e,t,r){S(e,r[2*t],r[2*t+1])}function E(e,t){for(var r=0;r|=1&e,e>>>=1,r<<=1,0<--t;);return r>>>1}function C(e,t,r){var n,i,s=new Array(_+1),a=0;for(n=1;n<=_;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=E(s[o]++,o))}}function A(e){var t;for(t=0;t<286;t++)e.dyn_ltree[2*t]=0;for(t=0;t<30;t++)e.dyn_dtree[2*t]=0;for(t=0;t<19;t++)e.bl_tree[2*t]=0;e.dyn_ltree[512]=1,e.opt_len=e.static_len=0,e.last_lit=e.matches=0}function I(e){8<e.bi_valid?x(e,e.bi_buf):0<e.bi_valid&&(e.pending_buf[e.pending++]=e.bi_buf),e.bi_buf=0,e.bi_valid=0}function O(e,t,r,n){var i=2*t,s=2*r;return e[i]<e[s]||e[i]===e[s]&&n[t]<=n[r]}function B(e,t,r){for(var n=e.heap[r],i=r<<1;i<=e.heap_len&&(i<e.heap_len&&O(t,e.heap[i+1],e.heap[i],e.depth)&&i++,!O(t,n,e.heap[i],e.depth));)e.heap[r]=e.heap[i],r=i,i<<=1;e.heap[r]=n}function T(e,t,r){var n,i,s,a,o=0;if(0!==e.last_lit)for(;n=e.pending_buf[e.d_buf+2*o]<<8|e.pending_buf[e.d_buf+2*o+1],i=e.pending_buf[e.l_buf+o],o++,0===n?z(e,i,t):(z(e,(s=p[i])+256+1,t),0!==(a=u[s])&&S(e,i-=m[s],a),z(e,s=k(--n),r),0!==(a=h[s])&&S(e,n-=w[s],a)),o<e.last_lit;);z(e,256,t)}function R(e,t){var r,n,i,s=t.dyn_tree,a=t.stat_desc.static_tree,o=t.stat_desc.has_stree,u=t.stat_desc.elems,h=-1;for(e.heap_len=0,e.heap_max=573,r=0;r<u;r++)0!==s[2*r]?(e.heap[++e.heap_len]=h=r,e.depth[r]=0):s[2*r+1]=0;for(;e.heap_len<2;)s[2*(i=e.heap[++e.heap_len]=h<2?++h:0)]=1,e.depth[i]=0,e.opt_len--,o&&(e.static_len-=a[2*i+1]);for(t.max_code=h,r=e.heap_len>>1;1<=r;r--)B(e,s,r);for(i=u;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],B(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,B(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,u=t.dyn_tree,h=t.max_code,f=t.stat_desc.static_tree,l=t.stat_desc.has_stree,d=t.stat_desc.extra_bits,c=t.stat_desc.extra_base,p=t.stat_desc.max_length,m=0;for(s=0;s<=_;s++)e.bl_count[s]=0;for(u[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<573;r++)p<(s=u[2*u[2*(n=e.heap[r])+1]+1]+1)&&(s=p,m++),u[2*n+1]=s,h<n||(e.bl_count[s]++,a=0,c<=n&&(a=d[n-c]),o=u[2*n],e.opt_len+=o*(s+a),l&&(e.static_len+=o*(f[2*n+1]+a)));if(0!==m){do{for(s=p-1;0===e.bl_count[s];)s--;e.bl_count[s]--,e.bl_count[s+1]+=2,e.bl_count[p]--,m-=2}while(0<m);for(s=p;0!==s;s--)for(n=e.bl_count[s];0!==n;)h<(i=e.heap[--r])||(u[2*i+1]!==s&&(e.opt_len+=(s-u[2*i+1])*u[2*i],u[2*i+1]=s),n--)}}(e,t),C(s,h,e.bl_count)}function D(e,t,r){var n,i,s=-1,a=t[1],o=0,u=7,h=4;for(0===a&&(u=138,h=3),t[2*(r+1)+1]=65535,n=0;n<=r;n++)i=a,a=t[2*(n+1)+1],++o<u&&i===a||(o<h?e.bl_tree[2*i]+=o:0!==i?(i!==s&&e.bl_tree[2*i]++,e.bl_tree[32]++):o<=10?e.bl_tree[34]++:e.bl_tree[36]++,s=i,h=(o=0)===a?(u=138,3):i===a?(u=6,3):(u=7,4))}function F(e,t,r){var n,i,s=-1,a=t[1],o=0,u=7,h=4;for(0===a&&(u=138,h=3),n=0;n<=r;n++)if(i=a,a=t[2*(n+1)+1],!(++o<u&&i===a)){if(o<h)for(;z(e,i,e.bl_tree),0!=--o;);else 0!==i?(i!==s&&(z(e,i,e.bl_tree),o--),z(e,16,e.bl_tree),S(e,o-3,2)):o<=10?(z(e,17,e.bl_tree),S(e,o-3,3)):(z(e,18,e.bl_tree),S(e,o-11,7));s=i,h=(o=0)===a?(u=138,3):i===a?(u=6,3):(u=7,4)}}n(w);var N=!1;function U(e,t,r,n){var i,s,a;S(e,0+(n?1:0),3),s=t,a=r,I(i=e),x(i,a),x(i,~a),o.arraySet(i.pending_buf,i.window,s,a,i.pending),i.pending+=a}r._tr_init=function(e){N||(function(){var e,t,r,n,i,s=new Array(_+1);for(n=r=0;n<28;n++)for(m[n]=r,e=0;e<1<<u[n];e++)p[r++]=n;for(p[r-1]=n,n=i=0;n<16;n++)for(w[n]=i,e=0;e<1<<h[n];e++)c[i++]=n;for(i>>=7;n<30;n++)for(w[n]=i<<7,e=0;e<1<<h[n]-7;e++)c[256+i++]=n;for(t=0;t<=_;t++)s[t]=0;for(e=0;e<=143;)l[2*e+1]=8,e++,s[8]++;for(;e<=255;)l[2*e+1]=9,e++,s[9]++;for(;e<=279;)l[2*e+1]=7,e++,s[7]++;for(;e<=287;)l[2*e+1]=8,e++,s[8]++;for(C(l,287,s),e=0;e<30;e++)d[2*e+1]=5,d[2*e]=E(e,5);g=new y(l,u,257,286,_),v=new y(d,h,0,30,_),b=new y(new Array(0),a,0,19,7)}(),N=!0),e.l_desc=new s(e.dyn_ltree,g),e.d_desc=new s(e.dyn_dtree,v),e.bl_desc=new s(e.bl_tree,b),e.bi_buf=0,e.bi_valid=0,A(e)},r._tr_stored_block=U,r._tr_flush_block=function(e,t,r,n){var i,s,a=0;0<e.level?(2===e.strm.data_type&&(e.strm.data_type=function(e){var t,r=4093624447;for(t=0;t<=31;t++,r>>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return 0;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return 1;for(t=32;t<256;t++)if(0!==e.dyn_ltree[2*t])return 1;return 0}(e)),R(e,e.l_desc),R(e,e.d_desc),a=function(e){var t;for(D(e,e.dyn_ltree,e.l_desc.max_code),D(e,e.dyn_dtree,e.d_desc.max_code),R(e,e.bl_desc),t=18;3<=t&&0===e.bl_tree[2*f[t]+1];t--);return e.opt_len+=3*(t+1)+5+5+4,t}(e),i=e.opt_len+3+7>>>3,(s=e.static_len+3+7>>>3)<=i&&(i=s)):i=s=r+5,r+4<=i&&-1!==t?U(e,t,r,n):4===e.strategy||s===i?(S(e,2+(n?1:0),3),T(e,l,d)):(S(e,4+(n?1:0),3),function(e,t,r,n){var i;for(S(e,t-257,5),S(e,r-1,5),S(e,n-4,4),i=0;i<n;i++)S(e,e.bl_tree[2*f[i]+1],3);F(e,e.dyn_ltree,t-1),F(e,e.dyn_dtree,r-1)}(e,e.l_desc.max_code+1,e.d_desc.max_code+1,a+1),T(e,e.dyn_ltree,e.dyn_dtree)),A(e),n&&I(e)},r._tr_tally=function(e,t,r){return e.pending_buf[e.d_buf+2*e.last_lit]=t>>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(p[r]+256+1)]++,e.dyn_dtree[2*k(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){var t;S(e,2,3),z(e,256,l),16===(t=e).bi_valid?(x(t,t.bi_buf),t.bi_buf=0,t.bi_valid=0):8<=t.bi_valid&&(t.pending_buf[t.pending++]=255&t.bi_buf,t.bi_buf>>=8,t.bi_valid-=8)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,r){"use strict";t.exports="function"==typeof setImmediate?setImmediate:function(){var e=[].slice.apply(arguments);e.splice(1,0,0),setTimeout.apply(null,e)}},{}]},{},[10])(10)})}).call(this,void 0!==r?r:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)})}).call(this,void 0!==r?r:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)})}).call(this,void 0!==r?r:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)})}).call(this,void 0!==r?r:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)});

var JAXDataObj;
let callAfter;

//***************************************************************************
//面向dataObj的方法:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化函数:
	JAXDataObj=function(jaxEnv,owner,ownerKey){
		var self;
		var notifyHubOn,notifyOnAll,notifyToMap;//即时/延时的派送通知函数

		if(jaxEnv===undefined){
			return;
		}
		self=this;//新建一个对象
		self.jaxEnv=jaxEnv;
		self.deadOut=0;
		self.jaxValNotify=1;
		self.owner=owner;
		self.ownerKey=ownerKey;

		//*******************************************************************
		//使当前self对象拥有可以追踪的变量相关:
		//*******************************************************************
		{
			var m_NotifyPaused;
			var m_viewHubIn = {};
			var m_viewHubOn = {};
			var m_isInEnvList = 0;
			var m_NotifyOnMsgHash = {};
			var m_PendingNofifyOn=[];
			var m_msgValHash={};
			var removeValBindOfView;

			//---------------------------------------------------------------
			//转换一个成员为被监测的:@[""+obj.name,"Data"]
			self.upgradeVal = function (name, msg) {
				var oldMsg, curVal, desc, oldGet, oldSet,msgList;
				if (!(name in self)) {
					return;
				}
				if (!msg) {
					msg = "*";//默认的分散消息通道:
				}
				if(Array.isArray(msg)){
					msgList=msg;
				}
				oldMsg = m_msgValHash[name];
				if (oldMsg) {
					if (msg !== oldMsg) {
						throw "JAXDataObj upgradVal error: val " + name + " is already been upgraded with diffrent msg " + oldMsg + ", new msg: " + msg;
					}
					return;
				}
				desc = Object.getOwnPropertyDescriptor(self, name);
				oldGet = desc.get;
				oldSet = desc.set;
				curVal = self[name];
				m_msgValHash[name] = msg;
				if(msgList){
					//纪录映射
					Object.defineProperty(self, name,
						{
							enumerable: desc.enumerable,
							configurable: true,
							set: function (newVal) {
								let msg;
								curVal = newVal;
								if (oldSet) {
									oldSet.call(self, newVal);
								}
								for(msg of msgList) {
									//notifyHubIn(msg);//这个要去掉
									notifyHubOn(msg);
								}
								return newVal;
							},
							get: function () {
								return oldGet ? oldGet.call(self) : curVal;
							}
						}
					);
				}else {
					//纪录映射
					Object.defineProperty(self, name,
						{
							enumerable: desc.enumerable,
							configurable: true,
							set: function (newVal) {
								curVal = newVal;
								if (oldSet) {
									oldSet.call(self, newVal);
								}
								//notifyHubIn(msg);//这个要去掉
								notifyHubOn(msg);
								return newVal;
							},
							get: function () {
								return oldGet ? oldGet.call(self) : curVal;
							}
						}
					);
				}
			};

			//---------------------------------------------------------------
			//得到一个变量对应的消息:
			self.getValMsg = function (name) {
				return m_msgValHash[name];
			};

			//---------------------------------------------------------------
			//添加延时数据观察回调，返回指定变量对应的msg
			self.onNotify=self.bindValNotify = function (valName,func,view,once=0) {
				var map, set, msg;
				if (!func) {
					console.error("hub notify function!!");
					return;
				}
				if (!(valName in self)) {
					msg=valName;
				}else {
					msg = m_msgValHash[valName];
				}
				if(!msg){
					throw ""+valName+" is not upgraded!";
				}
				map = m_viewHubOn[msg];
				if (!map) {
					map = m_viewHubOn[msg] = new Map();
				}
				set = map.get(view);
				if (!set) {
					set = new Set();
					map.set(view, set);
				}
				if(!once) {
					set.add(func);
				}else {
					let onceFunc;
					onceFunc=function(...args){
						func(...args);
						self.off(msg,onceFunc,view);
					};
					set.add(onceFunc);
				}
				return msg;
			};

			//---------------------------------------------------------------
			//添加单次延时数据观察回调
			self.onceNotify=function(msgName,func,view){
				self.onNotify(msgName,func,view,1);
			};

			//---------------------------------------------------------------
			//删除view对应的所有观察回调
			self.removeValBindOfView = removeValBindOfView = function (msgName, view) {
				var list, i;
				if (!msgName) {
					list = m_viewHubIn;
					for (i in list) {
						removeValBindOfView(i, view);
					}
					list = m_viewHubOn;
					for (i in list) {
						removeValBindOfView(i, view);
					}
					return;
				}
				list = m_viewHubIn[msgName];
				if (list) {
					list.delete(view);
				}
				list = m_viewHubOn[msgName];
				if (list) {
					list.delete(view);
				}
			};

			//---------------------------------------------------------------
			//删除指定的链接
			self.offNotify=self.removeValNotify = function (msgName, func, view) {
				var list, map, set, i, msg;
				if (!msgName) {
					list = m_viewHubIn;
					for (i in list) {
						msg=i;
						self.removeValNotify(msg, view, func);
					}
					list = m_viewHubOn;
					for (i in list) {
						msg=i;
						self.removeValNotify(i, view, func);
					}
					return;
				}
				map = m_viewHubIn[msgName];
				if (map) {
					set = map.get(view);
					if (set) {
						set.delete(func);
					}
				}
				map = m_viewHubOn[msgName];
				if (map) {
					set = map.get(view);
					if (set) {
						set.delete(func);
					}
				}
			};

			//---------------------------------------------------------------
			//通知指定消息队列里的函数:
			notifyToMap = function (map) {
				var views, view, set, func;
				views = map.keys();
				for (view of views) {
					if (!view || view.allowValNotify!==false) {
						set = map.get(view);
						for (func of set) {
							func();
						}
					}
				}
			};

			//---------------------------------------------------------------
			//延时通知函数:
			self.emitNotify=self.notifyValMsgOn = notifyHubOn = function (msg) {
				if (m_NotifyOnMsgHash[msg])
					return;
				m_NotifyOnMsgHash[msg] = 1;
				m_PendingNofifyOn.push(msg);
				if (m_isInEnvList)
					return;
				m_isInEnvList = 1;
				callAfter(notifyOnAll);
			};

			//---------------------------------------------------------------
			//发送延时通知函数:
			notifyOnAll = function () {
				var map, msg, list, loop;
				if (m_NotifyPaused)
					return;
				loop = 0;
				do {
					list = m_PendingNofifyOn.splice(0);
					for (msg of list) {
						m_NotifyOnMsgHash[msg] = 0;
						map = m_viewHubOn[msg];
						if (map) {
							notifyToMap(map);
						}
					}
					loop++;
					if (loop > 3)
						break;
				} while (m_PendingNofifyOn.length);
				m_isInEnvList = 0;
			};

			//---------------------------------------------------------------
			//定义暂停属性通知机制:
			Object.defineProperty(self,"pauseValNotify",{
				get:function(){
					return m_NotifyPaused;
				},
				set:function(v){
					v=v?1:0;
					m_NotifyPaused=v;
					return v;
				}
			});

			//---------------------------------------------------------------
			//得到当前使用的全部的消息
			self.eventNames=function(){
				//TODO: Code this:
				return [];
			};
		}
		return self;
	};
}

//***************************************************************************
//静态Class成员函数:
//***************************************************************************
{
	var DataTypeHash = {};

	//-----------------------------------------------------------------------
	//注册DataObj类型
	JAXDataObj.regHudByType = function (typeName, func) {
		DataTypeHash[typeName] = func;
	};

	//-----------------------------------------------------------------------
	//根据类型创建DataObj
	JAXDataObj.createDataObjByType=function(type,jaxEnv){
		var func;
		func=DataTypeHash[type];
		func=func?func:function(env){new JAXDataObj(env);};
		return func(jaxEnv);
	};
}
//***************************************************************************
//CallAfter:
//***************************************************************************
{
	let callAFList=[];
	let callInList=false;

	//-----------------------------------------------------------------------
	//Call a function later, make sure it's asynced:
	callAfter=JAXDataObj.callAfter=function(func)
	{
		callAFList.push(func);
		if(!callInList){
			callInList=true;
			setTimeout(()=>{
				let list=callAFList;
				callInList=0;
				callAFList=[];
				for(let func of list){
					func();
				}
			},0);
		}
	};
}

var JAXEnv,__Proto$j,$JXV,JAXStateProxy,$V;

var curHasher,hasherList=[];
var curHudView,hudViewList=[];
var curHudState,hudStateList=[];
var newHudStates=[];

var willUpdate=0;
var updateList=[];
var updateRequestRef=0;
var nextIncHash=0;
var curTimeHashTime=0;
var curTimeHashCnt=0;

var htmlBody=null;

// Kludges for bugs and behavior differences that can't be feature
// detected are enabled based on userAgent etc sniffing.
var userAgent = navigator.userAgent;
var platform = navigator.platform;

/gecko\/\d/i.test(userAgent);
var ie_upto10 = /MSIE \d/.test(userAgent);
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
var edge$1 = /Edge\/(\d+)/.exec(userAgent);
var ie = ie_upto10 || ie_11up || edge$1;
ie && (ie_upto10 ? document.documentMode || 6 : +(edge$1 || ie_11up)[1]);
var webkit = !edge$1 && /WebKit\//.test(userAgent);
webkit && /Qt\/\d+\.\d+/.test(userAgent);
!edge$1 && /Chrome\//.test(userAgent);
var presto = /Opera\//.test(userAgent);
var safari = /Apple Computer/.test(navigator.vendor);
/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
/PhantomJS/.test(userAgent);

var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2);
var android = /Android/.test(userAgent);
// This is woefully incomplete. Suggestions for alternative methods welcome.
ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
ios || /Mac/.test(platform);
/\bCrOS\b/.test(userAgent);
/win/i.test(platform);

var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
if (presto_version) { presto_version = Number(presto_version[1]); }
if (presto_version && presto_version >= 15) { presto = false; webkit = true; }

JAXEnv=function(jaxDiv)
{
	var self;

	self=this;
	htmlBody=document.body;
	this.jaxDiv=jaxDiv;
	this.app=null;
	this.onMouseUps=[];
	this.onMouseMoves=[];
	this.curDrag=null;
	this.thisUpdateProc=this.update.bind(this);
	document.addEventListener('mousedown',this.OnMouseDown.bind(this),false);//注册鼠标按下消息，在冒泡阶段
	document.addEventListener('mouseup',this.OnMouseUp.bind(this),false);//注册鼠标抬起消息，在冒泡阶段
	document.addEventListener('mousemove',this.OnMouseMove.bind(this),false);//注册鼠标移动消息，在冒泡阶段

	document.addEventListener("keydown",this.OnKeyDown.bind(this),true);
	document.addEventListener("keyup",this.OnKeyUp.bind(this),true);

	//响应窗口大小变化:
	let sizeTimer=null;
	window.onresize=function(){
		let w,h;
		console.log("Window width: "+window.innerWidth);
		console.log("Window height: "+window.innerHeight);
		//通知App:
		w=window.innerWidth;
		h=window.innerHeight;
		jaxDiv.style.width=w+"px";
		jaxDiv.style.height=h+"px";
		if(sizeTimer){
			clearTimeout(sizeTimer);
		}
		sizeTimer=setTimeout(()=>{
			sizeTimer=null;
			if(self.app){
				self.app.OnResize(w,h);
			}
		},1000);
	};

	//测量文本宽度用div，这个需要改进:
	this.textSizeDiv=document.createElement('div');
	this.textSizeDiv.style.position="absolute";
	this.textSizeDiv.style.top="-2000px";
	jaxDiv.appendChild(this.textSizeDiv);

	//打开选择文件对话框的辅助按钮
	this.webFileInput=document.getElementById("JAXFileInput");
	if(this.webFileInput) {
		this.webFileInput.onchange = function () {
			if (self.OnFileInputChange) {
				self.OnFileInputChange(this.files);
			}
			this.value="";
		};
	}

	//用来触发文件下载的辅助按钮
	this.webFileDownload=document.getElementById("JAXFileDownload");
};

__Proto$j=JAXEnv.prototype={};

//***************************************************************************
//文件路径工具函数:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//得到路径的文件名:
	JAXEnv.getFileName=function(path){
		var pos;
		pos=path.lastIndexOf("/");
		if(pos>=0){
			return path.substring(pos+1);
		}
		pos=path.lastIndexOf(":");
		if(pos>=0){
			return path.substring(pos+1);
		}
		return path;
	};

	//-----------------------------------------------------------------------
	//得到路径的不带类型的文件名:
	JAXEnv.getFileNameNoExt=function(path){
		var pos,fileName;
		pos=path.lastIndexOf("/");
		if(pos>=0){
			fileName=path.substring(pos+1);
		}else {
			pos = path.lastIndexOf(":");
			if (pos >= 0) {
				fileName=path.substring(pos + 1);
			}else {
				fileName = path;
			}
		}
		pos=fileName.lastIndexOf(".");
		if(pos>=0) {
			return fileName.substring(0,pos);
		}
		return fileName;
	};

	//-----------------------------------------------------------------------
	//得到路径的文件夹:
	JAXEnv.getPathDir=function(path){
		var pos;
		pos=path.lastIndexOf("/");
		if(pos>=0){
			return path.substring(0,pos);
		}
		pos=path.lastIndexOf(":");
		if(pos>=0){
			return path.substring(0,pos+1);
		}
		return "";
	};

	//-----------------------------------------------------------------------
	//得到路径的小写扩展名:
	JAXEnv.getFileExt=function(path){
		var pos;
		pos=path.lastIndexOf(".");
		if(pos>=0){
			return path.substring(pos+1).toLowerCase();
		}
		return "";
	};

	//-----------------------------------------------------------------------
	//计算相对路径:
	JAXEnv.divFilePath=function(filePath,basePath){
		var fileDirs,baseDirs,i,n;
		if(!basePath){
			return filePath;
		}
		fileDirs=filePath.split("/");
		baseDirs=basePath.split("/");
		n=Math.min(fileDirs.length,baseDirs.length);
		for(i=0;i<n;i++){
			if(fileDirs[0]===baseDirs[0]){
				fileDirs.shift();
				baseDirs.shift();
				i--;n--;
			}else {
				break;
			}
		}
		n=baseDirs.length;
		for(i=0;i<n;i++){
			fileDirs.unshift("..");
		}
		return fileDirs.join("/");
	};

	//-----------------------------------------------------------------------
	//合并相对路径:
	JAXEnv.genFilePath=function(basePath,filePath){
		let pts,diskPrefix,fileDirs,baseDirs,i,n;
		//找磁盘
		pts=basePath.split(":");
		if(pts.length===2){
			diskPrefix=pts[0]+":";
			basePath=pts[1];
		}else {
			diskPrefix="";
		}
		if(filePath.startsWith("/")){
			//绝对路径，看看要不要增加磁盘
			return diskPrefix+filePath;
		}
		let pos1=filePath.indexOf(":");
		let pos2=filePath.indexOf("/");
		if(pos1>0){
			if(pos2<0 || pos2>pos1){
				return filePath;//这个Path是包含磁盘路径的
			}
		}
		//移除"./"
		while(filePath.startsWith("./")){
			filePath=filePath.substring(2);
		}
		fileDirs=filePath.split("/");
		baseDirs=basePath.split("/");
		n=fileDirs.length;
		for(i=0;i<n;i++){
			if(fileDirs[i]===".."){
				fileDirs.shift();
				baseDirs.pop();
				i--;n--;
			}else {
				break;
			}
		}
		fileDirs=baseDirs.concat(fileDirs);
		fileDirs=fileDirs.filter((item,idx)=>(idx===0||(!!item && item!==".")));
		return diskPrefix+fileDirs.join("/");
	};

	//-----------------------------------------------------------------------
	//把磁盘路径转化为URL:
	JAXEnv.diskPath2URL=function(diskPath){
		let pos,diskName,filePath;
		if(diskPath.startsWith("/")){
			return "/jaxweb/disks"+diskPath;
		}
		pos=diskPath.indexOf(":");
		if(pos<0){
			throw "Can't find disk name from: "+diskPath;
		}
		diskName=diskPath.substring(0,pos);
		filePath=diskPath.substring(pos+1);
		if(filePath.startsWith("/")){
			filePath=filePath.substring(1);
		}
		return "/jaxweb/disks/"+diskName+"/"+filePath;
	};
}

//***************************************************************************
//CSS工具函数:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//链接CSS对象
	JAXEnv.linkCSSObj=function(obj){
		var cssObj;
		cssObj=obj.css;
		if(cssObj && typeof(cssObj)==='object'){
			this.linkCSSObj(cssObj);
			obj.__proto__=cssObj;
			obj.$JAXCssName="css";
			delete obj.css;
			return 1;
		}
		cssObj=obj.type;
		if(cssObj && typeof(cssObj)==='object'){
			this.linkCSSObj(cssObj);
			obj.__proto__=cssObj;
			obj.$JAXCssName="type";
			delete obj.css;
			return 1;
		}
		return 0;
	};

	//-----------------------------------------------------------------------
	//反链接CSS对象
	JAXEnv.unlinkCSSObj=function(obj)
	{
		var cssObj;
		cssObj=obj.__proto__;
		//cssObj=Object.getPrototypeOf(obj);
		if(cssObj&&obj.$JAXCssName){
			this.unlinkCSSObj(cssObj);
			obj[obj.$JAXCssName]=cssObj;
			obj.__proto__=null;
			delete obj.$JAXCssName;
			//Object.setPrototypeOf(obj,null);
		}
	};

	//-----------------------------------------------------------------------
	//CSS
	JAXEnv.applyCSS=function(obj,cssObj,pptSet)
	{
		let key,curCSSObj,val;
		let prtObj,hasCSS;

		hasCSS=this.linkCSSObj(cssObj);

		if(!pptSet){
			pptSet=obj.constructor.jaxPptSet;
		}
		if(!pptSet){
			pptSet=obj.jaxClassFunc.jaxPptSet;
		}
		if(typeof(obj.preApplyCSS)==='function'){
			obj.preApplyCSS(cssObj);
		}
		if(pptSet){
			for(key of pptSet){
				//console.log("Check ppt: "+key+"");
				//console.log("    ="+cssObj[key]);
				if(key in cssObj) {
					val=cssObj[key];
					if(val instanceof $JXV){
						obj[key] = val;
					}else if(typeof(val)==="string" && val.startsWith("${")&&val.endsWith("}")){
						throw "Old ${...} found!";
					}else {
						obj[key] = val;
					}
				}
			}
			curCSSObj=cssObj;
			for(let k in curCSSObj){//只有这样才能得到整个prototype链里全部的变量名:
				key=k;
				// if(cssObj.id==="btnName" && key==="name") {
				// 	console.log("Check ex ppt: " + key + "?" + pptSet.has(key) + "?" + (key in obj));
				// }
				if(!pptSet.has(key) && !(key in obj)){
					let desc;
					if(key.startsWith("%")) {
						//这是个参数定义，不是真正的Val:
						prtObj=cssObj;
						desc=null;
						while(prtObj && (!desc)){
							desc=Object.getOwnPropertyDescriptor(prtObj,key);
							prtObj=prtObj.__proto__;
						}
						if(desc&& (!("value" in desc))){
							let hasKey;
							key=key.substring(1);
							val=obj[key];
							hasKey=key in obj;
							Object.defineProperty(obj,key,desc);
							if(hasKey){
								obj[key]=val;
							}
						}
					}else {
						val = curCSSObj[key];
						if (val !== undefined) {
							if(val instanceof $JXV){
								obj[key] = val;
							}else if (typeof (val) === "string" && val.startsWith("${") && val.endsWith("}")) {
								throw "Old ${} found!";
							} else {
								obj[key] = val;
							}
						}
					}
				}
			}
		}else {
			curCSSObj=cssObj;
			do{
				for(key in curCSSObj){//只有这样才能得到整个prototype链里全部的变量名:
					if(!(key in obj)){
						val=curCSSObj[key];
						if(val!==undefined) {
							if(val instanceof $JXV) {
								obj[key] = val;
							}else if(typeof(val)==="string" && val.startsWith("${")&&val.endsWith("}")){
								throw "Old ${} found!";
							}else {
								obj[key] = val;
							}
						}
					}
				}
				curCSSObj=Object.getPrototypeOf(curCSSObj);
			}while(curCSSObj);
		}
		if(typeof(obj.finApplyCSS)==='function'){
			obj.finApplyCSS(cssObj);
		}
		if(hasCSS) {
			this.unlinkCSSObj(cssObj);
		}
		if(typeof(obj.postApplyCSS)==='function'){
			obj.postApplyCSS(cssObj);
		}
	};
}

//***************************************************************************
//有关Update的函数:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	__Proto$j.signUpdate=function(hud)
	{
		if(hud){
			updateList.push(hud);
		}else {
			throw "No hud to sign update"
		}

		if(willUpdate){
			return;
		}
		willUpdate=1;
		if(updateRequestRef){
			window.clearTimeout(updateRequestRef);
			updateRequestRef=0;
		}
		window.requestAnimationFrame(this.thisUpdateProc);
	};

	//-----------------------------------------------------------------------
	__Proto$j.update=function()
	{
		let list,hud;

		if(updateRequestRef){
			window.clearTimeout(updateRequestRef);
			updateRequestRef=0;
		}

		willUpdate=0;
		this.app.update();

		list=updateList.splice(0);
		for(hud of list){
			hud._update();
		}
	
		//JAXDataObj.update();

		if(!willUpdate){
			updateRequestRef=window.setTimeout(this.thisUpdateProc,50);
		}
	};
}

//***************************************************************************
//有关AF回调函数的函数:
//***************************************************************************
{
	__Proto$j.callAfter=JAXDataObj.callAfter;
}

//***************************************************************************
//有关ObjHasher/View/HudState的函数
//***************************************************************************
{
	let forceNewJaxId=0;

	//---------------------------------------------------------------------------
	//是否强制使用新的JaxId
	JAXEnv.isForceNewJaxId=function(){
		return forceNewJaxId?1:0;
	};

	//---------------------------------------------------------------------------
	//设置是否强制使用新的JaxId
	JAXEnv.setForceNewJaxId=function(v){
		if(v){
			forceNewJaxId++;
		}else {
			forceNewJaxId--;
		}
		forceNewJaxId=forceNewJaxId<=0?0:forceNewJaxId;
		return forceNewJaxId;
	};

	//---------------------------------------------------------------------------
	//验证一个jaxId
	JAXEnv.checkJaxId=function(jaxId){
		return forceNewJaxId?this.genTimeHash():jaxId;
	};

	//---------------------------------------------------------------------------
	//生成一个序号类的HashID:
	__Proto$j.genIncHash = function () {
		return "INC"+(nextIncHash++);
	};

	//---------------------------------------------------------------------------
	//生成一个时间类的HashID:
	JAXEnv.genTimeHash=__Proto$j.genTimeHash = function () {
		var time,hash;
		time=Date.now();
		hash=Number(time).toString(32);
		if(time===curTimeHashTime){
			curTimeHashCnt++;
		}else {
			curTimeHashCnt=0;
		}
		hash+=""+curTimeHashCnt;
		curTimeHashTime=time;
		return hash.toUpperCase();
	};

	//---------------------------------------------------------------------------
	//纪录(压入)当前的ObjHasher
	__Proto$j.pushObjHasher = function (obj) {
		if (curHasher) {
			hasherList.push(curHasher);
		}
		curHasher = obj;
	};

	//---------------------------------------------------------------------------
	//弹出当前的ObjHasher，
	__Proto$j.popObjHasher = function (obj) {
		if(!obj || obj===curHasher){
			curHasher = hasherList.pop();
		}
	};

	//---------------------------------------------------------------------------
	//给当前的ObjHasher增加一个纪录的对象
	__Proto$j.addHashObj = function (id,obj) {
		if (curHasher) {
			curHasher[id]=obj;
		}
	};

	//---------------------------------------------------------------------------
	//纪录(压入)当前的View
	__Proto$j.pushHudView = function (obj) {
		if (curHudView) {
			hudViewList.push(curHudView);
		}
		curHudView = obj;
	};

	//---------------------------------------------------------------------------
	//弹出当前的HudView，
	__Proto$j.popHudView = function (obj) {
		curHudView = hudViewList.pop();
	};

	//---------------------------------------------------------------------------
	//得到当前的HudView，
	__Proto$j.getHudView = function () {
		return curHudView;
	};


	//---------------------------------------------------------------------------
	//纪录(压入)当前的HudState
	__Proto$j.pushHudState = function (obj) {
		if (curHudState) {
			hudStateList.push(curHudState);
		}
		curHudState = obj;
	};

	//---------------------------------------------------------------------------
	//弹出当前的HudState，
	__Proto$j.popHudState = function (obj) {
		curHudState = hudStateList.pop();
	};

	//---------------------------------------------------------------------------
	//得到当前的HudState，
	__Proto$j.getCurHudState = function () {
		return curHudState;
	};

	//---------------------------------------------------------------------------
	//纪录新建的HudState
	__Proto$j.newHudState = function (obj) {
		newHudStates.push(obj);
	};

	//---------------------------------------------------------------------------
	//弹出当前的HudState，
	__Proto$j.finNewHudStates = function (finalObj,updateList,traceList) {
		var i,obj;
		finalObj.setupState_(null,null,updateList,traceList);
		for(i=0;i<newHudStates.length;i++){
			obj=newHudStates[i];
			if(!obj.ownerObj_){
				obj.setupState_(null,null,updateList,traceList);
			}
		}
		newHudStates.splice(0);
	};
}

//***************************************************************************
//鼠标/拖拽等事件函数
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//System handle mouse down:
	__Proto$j.OnMouseDown = function (e) {
		var drag;
		//drag:
		drag=this.curDrag;
		if(drag){
			let dx,dy;
			dx=e.x-drag.ox;
			dy=e.y-drag.oy;
			drag.OnDone(e,0,dx,dy);
			this.curDrag=null;
		}
	};
	
	//-----------------------------------------------------------------------
	//注册一个需要知道鼠标抬起消息回调函数
	__Proto$j.addOnMouseUp = function (func) {
		if (func._inJAXMouseUp) {
			return;
		}
		func._inJAXMouseUp = 1;
		this.onMouseUps.push(func);
	};

	//-----------------------------------------------------------------------
	//注销一个需要知道鼠标抬起消息回调函数
	__Proto$j.removeOnMouseUp = function (func) {
		func._inJAXMouseUp = 0;
	};
	
	//-----------------------------------------------------------------------
	//系统处理鼠标抬起消息:
	__Proto$j.OnMouseUp = function (e) {
		var list, i, n, func,drag;
		list = this.onMouseUps;
		n = list.length;
		for (i = 0; i < n; i++) {
			func=list[i];
			if(func._inJAXMouseUp){
				func(e,1);
			}else {
				list.splice(i,1);
				i--;n--;
			}
		}
		//drag:
		drag=this.curDrag;
		if(drag){
			let dx,dy;
			dx=e.x-drag.ox;
			dy=e.y-drag.oy;
			drag.OnDone(e,0,dx,dy);
			this.curDrag=null;
		}
	};

	//-----------------------------------------------------------------------
	//注册一个需要知道鼠标移动消息回调函数
	__Proto$j.addOnMouseMove = function (func) {
		if (func._inJAXMouseMove) {
			return;
		}
		func._inJAXMouseMove = 1;
		this.onMouseMoves.push(func);
	};

	//-----------------------------------------------------------------------
	//注销一个需要知道鼠标移动消息回调函数
	__Proto$j.removeOnMouseMove = function (func) {
		func._inJAXMouseMove = 0;
	};

	//-----------------------------------------------------------------------
	//系统处理鼠标移动消息:
	__Proto$j.OnMouseMove = function (e) {
		var list, i, n, func,drag;
		list = this.onMouseMoves;
		n = list.length;
		for (i = 0; i < n; i++) {
			func=list[i];
			if(func._inJAXMouseMove){
				func(e,1);
			}else {
				list.splice(i,1);
				i--;n--;
			}
		}
		//drag:
		drag=this.curDrag;
		if(drag){
			let dx,dy;
			dx=e.x-drag.ox;
			dy=e.y-drag.oy;
			drag.OnDrag(e,dx,dy);
			e.stopPropagation();
			e.preventDefault();
		}
	};

	//-----------------------------------------------------------------------
	//开始拖拽
	__Proto$j.startDrag=function(e,stub){
		if(this.curDrag){
			let dx,dy;
			dx=e.x-this.curDrag.ox;
			dy=e.y-this.curDrag.oy;
			this.curDrag.OnDone(e,1,dx,dy);
		}
		this.curDrag=stub;
		this.curDrag.ox=e.x;
		this.curDrag.oy=e.y;
	};

}

//***************************************************************************
//键盘消息/快捷键处理:
//***************************************************************************
{
	let OnKeyDowns=[];
	let OnKeyUps=[];

	//-----------------------------------------------------------------------
	//注册一个按键按下消息回调函数
	__Proto$j.addOnKeyDown = function (func) {
		if (func._inJAXKeyDown) {
			return;
		}
		func._inJAXKeyDown = 1;
		OnKeyDowns.push(func);
	};

	//-----------------------------------------------------------------------
	//注销一个按键按下消息回调函数
	__Proto$j.removeOnKeyDown = function (func) {
		func._inJAXKeyDown = 0;
	};

	//-----------------------------------------------------------------------
	//注册一个按键按下消息回调函数
	__Proto$j.addOnKeyUp = function (func) {
		if (func._inJAXKeyUp) {
			return;
		}
		func._inJAXKeyUp = 1;
		OnKeyUps.push(func);
	};

	//-----------------------------------------------------------------------
	//注销一个按键按下消息回调函数
	__Proto$j.removeOnKeyUp = function (func) {
		func._inJAXKeyUp = 0;
	};

	//-----------------------------------------------------------------------
	//键盘按下消息
	__Proto$j.OnKeyDown=function(e){
		let list,i,n,func,appMajor;
		appMajor=e.target===htmlBody;
		list=OnKeyDowns;
		n=list.length;
		for(i=0;i<n;i++){
			func=list[i];
			if(func._inJAXKeyDown){
				if(func(e,appMajor)){
					e.preventDefault();
					e.stopPropagation();
				}
			}else {
				list.splice(i,1);
				i--;n--;
			}
		}
	};

	//-----------------------------------------------------------------------
	//键盘抬起消息
	__Proto$j.OnKeyUp=function(e){
		let list,i,n,func,appMajor;
		appMajor=e.target===htmlBody;
		list=OnKeyUps;
		n=list.length;
		for(i=0;i<n;i++){
			func=list[i];
			if(func._inJAXKeyUp){
				if(func(e,appMajor)){
					e.preventDefault();
					e.stopPropagation();
				}
			}else {
				list.splice(i,1);
				i--;n--;
			}
		}
	};
}

//***************************************************************************
//有关类型转换的函数:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//判断字符串是不是CSS字符串:
	JAXEnv.isCSSColorString=function(text){
		var n;
		if(!text.startsWith("#")){
			return 0;
		}
		text=text.substring(1);
		n=text.length;
		if((n===3)||(n===6)||(n===8)){
			return parseInt(text,16)>=0?1:0;
		}
		return 0;
	};

	//-----------------------------------------------------------------------
	//RGBA值转换为CSS字符串:
	JAXEnv.encodeColor=function(color,alpha=1){
		var r,g,b,a;
		r=color[0];
		g=color[1];
		b=color[2];
		a=color[3];

		r=r<0?0:(r>255?255:r);
		g=g<0?0:(g>255?255:g);
		b=b<0?0:(b>255?255:b);
		a=a<0?0:(a>1?1:a);
		a*=255;
		r=r<10?("0"+Math.floor(r).toString(16)):(""+Math.floor(r).toString(16));
		g=g<10?("0"+Math.floor(g).toString(16)):(""+Math.floor(g).toString(16));
		b=b<10?("0"+Math.floor(b).toString(16)):(""+Math.floor(b).toString(16));
		a=a<10?("0"+Math.floor(a).toString(16)):(""+Math.floor(a).toString(16));
		return alpha?("#"+r+g+b+a):("#"+r+g+b);
	};

	//-----------------------------------------------------------------------
	//颜色字符串转为RBGA值:
	JAXEnv.parseColor=function(text){
		var len,r,g,b,a;
		len=text.length;
		if(text.startsWith("#")){
			switch(len){
				case 4://#RGB
					r=text.substring(1,2);
					g=text.substring(2,3);
					b=text.substring(3,4);

					r=parseInt(r,16);
					r=isNaN(r)?0:(r*16+15);

					g=parseInt(g,16);
					g=isNaN(g)?0:(g*16+15);

					b=parseInt(b,16);
					b=isNaN(b)?0:(b*16+15);

					a=1;
					break;
				case 7://#RRGGBB
					r=text.substring(1,3);
					g=text.substring(3,5);
					b=text.substring(5,7);

					r=parseInt(r,16);
					r=isNaN(r)?0:(r);

					g=parseInt(g,16);
					g=isNaN(g)?0:(g);

					b=parseInt(b,16);
					b=isNaN(b)?0:(b);

					a=1;
					break;
				case 9://#RRGGBBAA
					r=text.substring(1,3);
					g=text.substring(3,5);
					b=text.substring(5,7);
					a=text.substring(7,9);

					r=parseInt(r,16);
					r=isNaN(r)?0:(r);

					g=parseInt(g,16);
					g=isNaN(g)?0:(g);

					b=parseInt(b,16);
					b=isNaN(b)?0:(b);

					a=parseInt(a,16);
					a=isNaN(a)?1:(a/255.0);
					break;
				default:
					return [0,0,0,1];
			}
			return [r,g,b,a];
		}
		//TODO: 增加其它颜色模式分析:
		return [0,0,0,1];
	};

	//-----------------------------------------------------------------------
	//数字转换为颜色数组:
	JAXEnv.num2Color=function(num){
		let r,g,b,a;
		num=Math.floor(num);
		a=(num&0xFF000000)>>24;
		r=(num&0xFF0000)>>16;
		g=(num&0xFF00)>>8;
		b=(num&0xFF);
		a=a/255;
		return [r,g,b,a];
	};

	//-----------------------------------------------------------------------
	//颜色数组转换为数字:
	JAXEnv.color2Num=function(color){
		let r,g,b,a;
		r=color[0];
		g=color[1];
		b=color[2];
		a=color[3];
		r=Math.floor(r<0?0:(r>255?255:r));
		g=Math.floor(g<0?0:(g>255?255:g));
		b=Math.floor(b<0?0:(b>255?255:b));
		a*=255;
		a=Math.floor(a<0?0:(a>255?255:a));
		return (a<<24)|(r<<16)|(g<<8)|b;
	};
}

//***************************************************************************
//属性的DYNA赋值
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//用来鉴别一个对象是不是JAXHudState的辅助类:
	JAXStateProxy=function(orgObj){
		this.orgObj=orgObj;
	};

	//-----------------------------------------------------------------------
	//JAX系统追踪动态变量:
	$V=$JXV=function(funcGet,traces,isNew=1){
		var val,func,defaultTgt,traced,traceView;
		if(isNew){
			return new $JXV(funcGet,traces,0);
		}
		defaultTgt=null;
		traced=0;
		traceView=null;
		if(traces) {
			val = funcGet();
		}
		this.func=function(obj,key){
			if(func){
				return func;
			}
			func=function(){obj[key]=funcGet();};
			return func;
		};
		Object.defineProperty(this,"val",{
			get:function(){
				//如果不是追踪模式的，每次调用funcGet:
				return traces?val:funcGet();
			}
		});
		if(traces){
			if(Array.isArray(traces)){
				let i,n,list,stub;
				list=traces;
				if(list.length===2 && typeof(list[1])==="string"){
					//This is oK:
					this.traces=traces=[traces];
				}else {
					for (i = 0; i < n; i++) {
						stub = list[i];
						if(typeof(stub)==="string"){
							list[i] =[null,stub];
						}else if (stub instanceof JAXDataObj || stub instanceof JAXStateProxy) {
							list[i] = [stub, "*"];
						} else if (Array.isArray(stub)) ; else if (stub.obj) {
							//对象转换为数组:
							list[i] = [stub.obj, stub.msg || stub.val || "*"];
						} else {
							//无效的追踪:
							list.splice(i, 1);
							i--;
							n--;
						}
					}
					if (list.length) {
						traces=this.traces = list;
					}
				}
			}else {
				if(traces instanceof JAXDataObj || traces instanceof JAXStateProxy){
					traces=this.traces=[[traces,"*"]];
				}else if(traces.obj){
					traces=this.traces=[[traces.obj,traces.msg||traces.val||"*"]];
				}else if(typeof(traces)==="string"){
					this.traces=traces;
				}else {
					traces=null;
				}
			}
		}else {
			this.traces=traces===0?0:null;
		}

		//-------------------------------------------------------------------
		//设置追踪:
		this.trace=function(defaultTgt_,ownerObj,valName,view){
			defaultTgt=defaultTgt_;
			traceView=view;
			if(!traces){
				if(defaultTgt){
					if(defaultTgt instanceof JAXStateProxy){
						defaultTgt.addUpdateFunc(func?func:this.func(ownerObj,valName));
						traced=1;
					}
				}
			}
			if(typeof(traces)==="string"){
				defaultTgt.onNotify(traces,func?func:this.func(ownerObj,valName),view);
				traced=1;
			}else if(Array.isArray(traces)){
				let i,n,stub,tgt,msg;
				n=traces.length;
				for(i=0;i<n;i++){
					stub=traces[i];
					stub[0]=tgt=stub[0]||defaultTgt;
					stub[1]=msg=stub[1]||"*";
					if(tgt) {
						tgt.onNotify(msg, func ? func : this.func(ownerObj, valName), view);
					}
				}
				traced=1;
			}
		};

		//-------------------------------------------------------------------
		//取消追踪
		this.untrace=function(){
			if(!traced || !func){
				return;
			}
			if(!traces){
				if((defaultTgt instanceof JAXStateProxy) &&(!defaultTgt.deadOut)){
					defaultTgt.removeUpdateFunc(func);
				}
			}else {
				if(typeof(traces)==="string"){
					defaultTgt.removeUpdateFunc(traces,func,traceView);
				}else if(Array.isArray(traces)){
					let i,n,stub,tgt,msg;
					n=traces.length;
					for(i=0;i<n;i++){
						stub=traces[i];
						tgt=stub[0];
						msg=stub[1];
						if(tgt.removeValNotify){
							tgt.offNotify(msg,func,traceView);
						}
					}
				}
			}
			traced=0;
		};
	};
}

var JAXAni,__Proto$i;

const STATE_NONE=0;
const STATE_READY$4=1;
const STATE_ANI$4=2;

//---------------------------------------------------------------------------
//JAX中的动画，动画都是与时间相关的
JAXAni=function(env,def=null,hud=null)
{
	if(!env)
		return;
	this.jaxEnv=env;
	this.startTime=0;
	this.endTime=0;
	this.state=0;
	this.hud=null;
	this.state=STATE_NONE;
	this.OnFinish=null;
	this.OnCanel=null;
	if(def){
		this.initByDef(def);
	}
	if(hud){
		this.bind2Hud(hud);
	}
};
__Proto$i=JAXAni.prototype={};

//***************************************************************************
//注册Ani类型/创建Ani:
//***************************************************************************
{
	var HudTypeHash$1 = {};

	//---------------------------------------------------------------------------
	//注册Hud控件类型
	JAXAni.regHudByType = function (typeName, func) {
		HudTypeHash$1[typeName] = func;
	};

	//---------------------------------------------------------------------------
	//根据类型创建Ani
	JAXAni.createAniByType = function (typeName, env, css,hud) {
		let typeType,func,ani;
		typeType=typeof(typeName);
		if(typeType==="string") {
			func = HudTypeHash$1[typeName];
		}
		ani=func(env,css,hud);
		return ani;
	};
}

//***************************************************************************
//通用接口:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化:
	__Proto$i.initByDef = function (def) {
		if (this.def) {
			this.jaxEnv.logError("Ani already inited.");
			return;
		}
		this.def = def;
		if (this.hud) {
			this.state = STATE_READY$4;
		}
	};

	//-----------------------------------------------------------------------
	//与Hud绑定:
	__Proto$i.bind2Hud = function (hud) {
		this.hud = hud;
		if (this.def) {
			this.state = STATE_READY$4;
		}
	};

	//-----------------------------------------------------------------------
	//开始动画
	__Proto$i.start = function () {
		if (this.state !== STATE_READY$4) {
			this.jaxEnv.logError("Ani not ready!");
			return;
		}
		this.startTime = Date.now();
		this.state = STATE_ANI$4;
	};

	//-----------------------------------------------------------------------
	//暂停动画:
	__Proto$i.pause = function () {
		//TODO: Code this:
	};

	//-----------------------------------------------------------------------
	//恢复动画:
	__Proto$i.resume = function () {
		//TODO: Code this:
	};

	//-----------------------------------------------------------------------
	//停止动画:
	__Proto$i.finish = function () {
		//TODO: Code this:
	};

	//-----------------------------------------------------------------------
	//取消动画:
	__Proto$i.cancel = function () {
		//TODO: Code this:
	};
}

var jaxHudState_,jaxHudState;

//***************************************************************************
//面向hudState的方法:
//***************************************************************************
{
	//---------------------------------------------------------------------------
	//生成hudState数组Proxy:
	jaxHudState_=function(jaxEnv,orgObj,isTopObj,opts)
	{
		var val;
		var self,ownerObj,ownerKey;
		var notifyOnAll,notifyToSet;//即时/延时的派送通知函数
		var valFuncsOnUpdate;
		var selfReady=0;
		var fullAuto;
		var willAutoNotifyAll=0;
		var jxvValMap=new Map();
		var subStates=new Set();

		//看看是不是已经是JAXStateProxy了:
		if(orgObj instanceof JAXStateProxy){
			return orgObj;
		}
		if(orgObj.constructor!==Object){
			if(isTopObj) {
				throw "Can only init state-object on a pure Object!";
			}
			return orgObj;
		}

		valFuncsOnUpdate=[];
		if(!opts){
			opts={
				fullAuto:1,
			};
		}
		fullAuto=opts.fullAuto;

		//创建Proxy:
		self=new Proxy(new JAXStateProxy(orgObj),{
			get:function(obj,pName){
				//如果是数组的话，是不是要某些函数需要替换支持改变的消息
				switch(pName){
					case "isJAXHudState":
						return true;
					case "ownerObj_":
						return ownerObj;
					case "ownerKey_":
						return ownerKey;
				}
				val=orgObj[pName];
				return val;
			},
			set:function(obj,pName,val) {
				let oldV,oldJXV;
				switch (pName) {
					case "ownerObj_":
						if (ownerObj) {
							throw "Error: jaxHudStateObj can't have more than one owner."
						}
						ownerObj = val;
						return ownerObj;
					case "ownerKey_":
						ownerKey = val;
						return ownerKey;
				}
				oldV=orgObj[pName];
				if(oldV instanceof JAXStateProxy){
					subStates.delete(oldV);
				}
				if(val instanceof $JXV) {
					oldJXV=jxvValMap.get(pName);
					if(oldJXV){
						oldJXV.untrace();
						jxvValMap.delete(pName);
					}
					orgObj[pName] = val.val;
					val.trace(orgObj.ownerState, self, pName, orgObj.hudView);
				}else if(val instanceof JAXStateProxy){
					orgObj[pName] = val;
					subStates.add(val);
				}else {
					orgObj[pName] = val;
				}
				if(selfReady) {
					//通知变量改变:
					self.valNotifyOn(pName);
					if (ownerObj) {
						ownerObj.valNotifyOn(ownerKey);
					}
					if(isTopObj && fullAuto && !willAutoNotifyAll){
						willAutoNotifyAll=1;
						jaxEnv.callAfter(()=>{
							self.update();
						});
					}
				}
				return true;
			}
		});
		self.isJAXHudState=1;

		//*************************************************************************
		//使当前self对象拥有可以追踪的变量相关:
		//*************************************************************************
		{
			var m_NotifyPaused;
			var m_viewHubOn = {};
			var m_isInEnvList = 0;
			var m_NotifyOnMsgHash = {};
			var m_PendingNofifyOn=[];

			//-------------------------------------------------------------------------
			//添加延时数据观察回调，返回指定变量对应的msg
			self.onNotify=self.bindValNotify = function (valName, func, view) {
				var set;
				if (!func) {
					return;
				}
				if (!(valName in self)) {
					return;
				}
				set = m_viewHubOn[valName];
				if (!set) {
					set = new Set();
					m_viewHubOn[valName]=set;
				}
				set.add(func);
				return valName;
			};

			//-------------------------------------------------------------------------
			//移除绑定的函数:
			self.offNotify=self.removeValNotify=function(valName,func,view){
				let set;
				if (func) {
					set = m_viewHubOn[valName];
					if (set) {
						set.delete(func);
					}
				}
			};

			//-------------------------------------------------------------------------
			//通知指定消息队列里的函数:
			notifyToSet = function (set) {
				var func;
				for (func of set) {
					func();
				}
			};

			//-------------------------------------------------------------------------
			//延时通知函数:
			self.valNotifyOn = function (msg) {
				if (m_NotifyOnMsgHash[msg])
					return;
				m_NotifyOnMsgHash[msg] = 1;
				m_PendingNofifyOn.push(msg);
				if (m_isInEnvList)
					return;
				m_isInEnvList = 1;
				jaxEnv.callAfter(notifyOnAll);
			};

			//-------------------------------------------------------------------------
			//发送延时通知函数:
			notifyOnAll = function () {
				var set, msg, list, loop;
				if (m_NotifyPaused)
					return;
				loop = 0;
				do {
					list = m_PendingNofifyOn.splice(0);
					for (msg of list) {
						m_NotifyOnMsgHash[msg] = 0;
						set = m_viewHubOn[msg];
						if (set) {
							notifyToSet(set);
						}
					}
					loop++;
					if (loop > 3)
						break;
				} while (m_PendingNofifyOn.length);
				m_isInEnvList = 0;
			};
		}

		//*************************************************************************
		//转换State项目里的变量/追踪函数
		//*************************************************************************
		{
			//-------------------------------------------------------------------------
			//根据字符串解析Trace的对象和变量:
			self.setupState_=function(ownerObj,ownerKey){
				let i,n;
				if(selfReady){
					throw "Error: HudState setup called more than once!";
				}
				jaxEnv.getHudView();
				if(Array.isArray(orgObj)){
					let newArray;
					newArray=orgObj;
					n=newArray.length;
					for(i=0;i<n;i++){
						val=newArray[i];
						if(val instanceof $JXV){
							jxvValMap.set(i,val);
							orgObj[i]=val.val;
							val.trace(orgObj.ownerState,self,i,orgObj.hudView);
						}else if(typeof(val)==="string" && val.startsWith("${") && val.endsWith("}")){
							throw "Old ${} found!";
						}
						if(val && val.isJAXHudState){
							val.setupState_(self,i);
						}
					}
				}else {
					let valKey,key,val;
					for(valKey in orgObj){
						key=valKey;
						val=orgObj[key];
						//看看Val是不是追踪表达式:
						if(val instanceof $JXV) {
							jxvValMap.set(key,val);
							orgObj[key]=val.val;
							val.trace(orgObj.ownerState,self,key,ownerObj.hudView);
						}else if(typeof(val)==="string" && val.startsWith("${") && val.endsWith("}")){
							throw "Old ${} found!";
						}
						if(val && val.isJAXHudState && key!=="ownerState"){
							val.ownerState=self;
							val.hudView=orgObj.hudView;
							val.setupState_(self,key);
						}
					}
				}
				selfReady=1;
			};
		}

		//添加一个update函数:
		self.addUpdateFunc=function(func){
			if(func){
				valFuncsOnUpdate.push(func);
				return func;
			}
			return null;
		};

		//移除一个update函数:
		self.removeUpdateFunc=function(func){
			let idx=valFuncsOnUpdate.indexOf(func);
			if(idx>=0){
				valFuncsOnUpdate.splice(idx,1);
			}

		};

		//更新state，通知全部与state的update绑定的hud/对象属性:
		self.update=function(sub=1){
			let func,list;
			willAutoNotifyAll=0;
			for(func of valFuncsOnUpdate){
				func();
			}
			if(sub) {
				list = subStates.values();
				for (let sub of list) {
					sub.update(1);
				}
			}
			self.OnUpdate&&self.OnUpdate();
		};

		//更新state，通知全部与state的update绑定的hud/对象属性:
		self.refresh=function(sub=1){
			let func,list,jxv;
			for(func of valFuncsOnUpdate){
				func();
			}
			list=jxvValMap.values();
			for(jxv of list){
				jxv.func()();
			}
			list=subStates.values();
			for(let sub of list){
				sub.update(1);
			}
		};


		//释放state
		self.freeState=function(){
			var jxv,list;
			this.deadOut=1;
			list=jxvValMap.values();
			for(jxv of list){
				jxv.untrace();
			}
			list=subStates.values();
			for(let sub of list){
				sub.freeState();
			}
		};

		if(isTopObj){
			self.setupState=function(hud,ownerState,hudView){
				orgObj.ownerState=ownerState;
				orgObj.hudView=hudView;
				self.setupState_(hud,"hudState");
			};
		}
		return self;
	};

	//---------------------------------------------------------------------------
	//生成顶级hudState:
	jaxHudState=function(jaxEnv,orgObj,opts){
		return jaxHudState_(jaxEnv,orgObj,1,opts);
	};
}

var JAXHudObj,__Proto$h;

__Proto$h={};
//---------------------------------------------------------------------------
//JAX的Hud控件基类
JAXHudObj=function(jaxEnv)
{
	var self,valJXVMap;
	var signUpdate_,signUpdate,isSignedUpdate;
	var jaxId,position,pos,size,autoLayout;
	var display,uiEvent,id,jaxObjHash,anchorH,anchorV,clip;
	var margin_t,margin_b,margin_l,margin_r;
	var layoutXFunc_,layoutYFunc_,layoutWFunc_,layoutHFunc_;
	var oldW,oldH;
	var hudPose,_poseChanged;
	var refCount,pxChdList;
	var grayScale;
	var filter;
	var curFaceVO,curFace,facesVO;
	var hudView;
	var attach;
	var cursor;

	if(!jaxEnv){
		return;
	}

	this.jaxClassFunc=JAXHudObj;

	self=this;
	jaxId="";
	jaxObjHash=null;

	valJXVMap=new Map();
	this.$valJXVMap=valJXVMap;

	id="";
	position="absolute";
	pos=[0,0,0];
	size=[0,0,0];
	margin_t=0;
	margin_b=0;
	margin_l=0;
	margin_r=0;
	this.jaxAcceptMsg=1;

	isSignedUpdate=0;
	signUpdate_=jaxEnv.signUpdate.bind(jaxEnv,this);
	signUpdate=function(){
		if(!isSignedUpdate){
			signUpdate_();
			isSignedUpdate=1;
		}
	};
	this.signUpdate=signUpdate;

	autoLayout=0;

	attach=1;

	layoutXFunc_=null;
	layoutYFunc_=null;
	layoutWFunc_=null;
	layoutHFunc_=null;
	oldW=0;
	oldH=0;

	display=1;
	uiEvent=1;
	anchorH=0;
	anchorV=0;
	grayScale=0;
	filter=null;
	clip=0;
	_poseChanged=0;
	hudPose={scale:1,alpha:1,rot:0};
	cursor="auto";

	curFaceVO=null;
	curFace="";
	facesVO=null;

	refCount=1;


	this.jaxEnv=jaxEnv;
	this.webObjTag='div';
	this.webObj=null;		//对应的HTML节点
	this.app=jaxEnv.app;
	this.anis=[];
	this.items2Add_=null;
	this.isJAXHudObj_=1;
	this._holdAttr=true;

	//Event functions:
	this.OnClickFunc_=null;
	this.OnTreeClickFunc_=null;
	this.OnScrollFunc_=null;
	this.OnLayoutFunc_=null;
	this.OnMouseInOutFunc_=null;

	//Attrs not enumerable:
	Object.defineProperty(this, 'isJAXHudObj_', {enumerable:false,writable:false});
	Object.defineProperty(this, 'jgxEnv', {enumerable:false,writable:false});
	Object.defineProperty(this, 'webObj', {enumerable:false,writable:true});
	Object.defineProperty(this, 'app', {enumerable:false,writable:false});
	Object.defineProperty(this, 'father_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'owner_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'chdHudList_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'anis', {enumerable:false,writable:false});
	Object.defineProperty(this, 'hudPose', {
		value:hudPose,
		enumerable:false,writable:false
	});
	Object.defineProperty(this, 'poseChanged', {
		get:function(){return _poseChanged;},
		set:function(v){_poseChanged=v;},
		enumerable:false
	});


	this.father_=null;
	this.owner_=null;
	this.chdHudList_=[];

	pxChdList=new Proxy(this.chdHudList_,{
		get:function(obj,pName){
			if(pName>=0 && pName<obj.length){
				return obj[pName];
			}else if(pName==='length'){
				return obj.length
			}
			return undefined;
		},
		set:function(obj,pName,v){}
	});

	//***********************************************************************
	//Component CSS attr access:
	//***********************************************************************
	{
		let func,father;
		let webObj;
		//-------------------------------------------------------------------
		Object.defineProperty(this, 'groupAttr', {
			get: function () {
				return this._holdAttr;
			},
			set: function (v) {
				if (v) {
					this._holdAttr=true;
				}else {
					if(_poseChanged){
						this._syncWebObj();
					}
				}
			},
			enumerable: true,
		});
		
		//-------------------------------------------------------------------
		Object.defineProperty(this, 'style', {
			get: function () {
				if(this.webObj) {
					return this.webObj.style;
				}
				return null;
			},
			set: function (v) {
				let webObj=this.webObj;
				if(webObj) {
					if (typeof (v) === "string") {
						webObj.style.cssText += v;
					} else {
						Object.assign(webObj.style, v);
					}
				}
			},
			enumerable: true,
		});
		
		//-------------------------------------------------------------------
		//ID/名称/索引等:
		{
			//控件jaxID快查表，这个用来
			Object.defineProperty(this, 'jaxObjHash', {
				get: function () {
					return this.jaxId;
				},
				set: function (v) {
					if (v) {
						jaxObjHash = typeof (v) === 'object' ? v : this;
						jaxEnv.pushObjHasher(jaxObjHash);
					}
				},
				enumerable: true,
			});

			//控件jaxID，这个用来
			Object.defineProperty(this, 'jaxId', {
				get: function () {
					return jaxId;
				},
				set: function (v) {
					jaxId = v;
					jaxEnv.addHashObj("#"+v, this);
				},
				enumerable: true,
			});

			//控件ID，随时同步
			Object.defineProperty(this, 'id', {
				get: function () {
					return id;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('id');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('id');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'id', hudView);
							valJXVMap.set('id', v);
						}
						v=v.val;
					}
					if (id !== v) {
						id = v;
						if (this.webObj) {
							this.webObj.id = id;
						}
						if(v){
							jaxEnv.addHashObj("" + v, this);
						}
					}
				},
				enumerable: true,
			});
		}

		//-------------------------------------------------------------------
		//尺寸/坐标/对齐:
		{
			let genAnchorStr=function(){
				let str;
				switch(anchorH)
				{
					case 0:
					default:
						str="left ";
						break;
					case 1:
						str="center ";
						break;
					case 2:
						str="right ";
						break;
				}
				switch(anchorV)
				{
					case 0:
					default:
						str+="top";
						break;
					case 1:
						str+="center";
						break;
					case 2:
						str+="bottom";
						break;
				}
				return str;
			};
			let genXStr=function(){
				switch(anchorH){
					case 0:
					default:
						return ""+pos[0]+"px";
					case 1:
						return ""+(pos[0]-(size[0]*0.5))+"px";
					case 2:
						return ""+(pos[0]-(size[0]))+"px";
				}
			};
			let genYStr=function(){
				switch(anchorV){
					case 0:
					default:
						return ""+pos[1]+"px";
					case 1:
						return ""+(pos[1]-(size[1]*0.5))+"px";
					case 2:
						return ""+(pos[1]-(size[1]))+"px";
				}
			};
			
			//Position:
			Object.defineProperty(this,'position',{
				get:function(){
					return position;
				},
				set:function(v){
					if(v!==position){
						let webObj;
						position=v;
						webObj=self.webObj;
						if(webObj){
							webObj.style.position=v;
						}
					}
				},
				enumerable: true,
				configurable:true
			});
		
			//控件是否自动排版
			Object.defineProperty(this, 'autoLayout', {
				get:function(){
					return autoLayout
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('autoLayout');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('autoLayout');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'autoLayout', hudView);
							valJXVMap.set('autoLayout', v);
						}
						v=v.val;
					}
					if(v!==autoLayout){
						autoLayout=v;
						if(v){
							this._doLayout();
						}
					}
				},
				enumerable: true
			});

			//控件的坐标，为了性能未必和真实Web元素一样，在一次Update之后才能同步
			Object.defineProperty(this, 'pos', {
				value: pos,
				writable: false,
				enumerable: false
			});

			//控件的尺寸，为了性能未必和真实Web元素一样，在一次Update之后才能同步
			Object.defineProperty(this, 'size', {
				value: size,
				writable: false,
				enumerable: false
			});

			//控件宽度
			Object.defineProperty(this, 'w', {
				get: function () {
					return this.size[0];
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('w');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('w');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'w', hudView);
							valJXVMap.set('w', v);
						}
						v=v.val;
					}
					if(typeof(v)==="string"){
						func=new Function("FW","FH","return ("+v+")");
						father=this.father_||this.owner_||jaxEnv.jaxDiv;
						layoutWFunc_=func;
						v = func(father.clientW, father.clientH);
					}else {
						layoutWFunc_=null;
					}
					if (size[0] !== v) {
						webObj=this.webObj;
						size[0] = v;
						if(this._holdAttr||!webObj){
							_poseChanged = 1;
						}else {
							webObj.style.width=""+v+"px";
							if(anchorH){
								webObj.style.left=genXStr();
							}
						}
						signUpdate();
					}
				},
				enumerable: true,
				configurable:true
			});

			//控件高度
			Object.defineProperty(this, 'h', {
				get: function () {
					return this.size[1];
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('h');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('h');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'h', hudView);
							valJXVMap.set('h', v);
						}
						v=v.val;
					}
					if(typeof(v)==="string"){
						func=new Function("FW","FH","return ("+v+")");
						father=this.father_||this.owner_|| jaxEnv.jaxDiv;
						layoutHFunc_=func;
						if(father) {
							v = func(father.clientW, father.clientH);
						}
					}else {
						layoutHFunc_=null;
					}
					if (size[1] !== v) {
						webObj=this.webObj;
						size[1] = v;
						if(this._holdAttr||!webObj){
							_poseChanged = 1;
						}else {
							webObj.style.height=""+v+"px";
							if(anchorV){
								webObj.style.top=genYStr();
							}
						}
						signUpdate();
					}
				},
				enumerable: true,
				configurable:true
			});

			//控件X坐标
			Object.defineProperty(this, 'x', {
				get: function () {
					return this.pos[0];
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('x');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('x');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'x', hudView);
							valJXVMap.set('x', v);
						}
						v=v.val;
					}
					if(typeof(v)==="string"){
						let func, father;
						func = new Function("FW", "FH", "return (" + v + ")");
						father = this.father_ || this.owner_ || jaxEnv.jaxDiv;
						layoutXFunc_ = func;
						if (father) {
							v = func(father.clientW, father.clientH);
						}
					}else {
						layoutXFunc_ = null;
					}
					if (v !== pos[0]) {
						webObj=this.webObj;
						pos[0] = v;
						if(this._holdAttr||!webObj) {
							_poseChanged = 1;
							signUpdate();
						}else {
							v= genXStr();
							webObj.style.left=v;
						}
					}
				},
				enumerable: true,
				configurable:true
			});

			//控件Y坐标
			Object.defineProperty(this, 'y', {
				get: function () {
					return this.pos[1];
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('y');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('y');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'y', hudView);
							valJXVMap.set('y', v);
						}
						v=v.val;
					}
					if(typeof(v)==="string"){
						func = new Function("FW", "FH", "return (" + v + ")");
						father = this.father_ || this.owner || jaxEnv.jaxDiv;
						layoutYFunc_ = func;
						v = func(father.clientW, father.clientH);
					}else {
						layoutYFunc_ = null;
					}
					if (v !== pos[1]) {
						webObj=this.webObj;
						pos[1] = v;
						if(this._holdAttr||!webObj) {
							_poseChanged = 1;
							signUpdate();
						}else {
							v= genYStr();
							webObj.style.top=v;
						}
					}
				},
				enumerable: true,
				configurable:true
			});

			//Z-Index:
			Object.defineProperty(this, 'zIndex', {
				get: function () {
					return this.pos[1];
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('zIndex');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('zIndex');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'zIndex', hudView);
							valJXVMap.set('zIndex', v);
						}
						v=v.val;
					}
					if(this.webObj){
						this.webObj.style.zIndex=""+v;
					}
				},
				enumerable: true
			});
			
			//控件X方向锚点位置
			Object.defineProperty(this, 'anchorH', {
				get: function () {
					return anchorH;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('anchorH');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('anchorH');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'anchorH', hudView);
							valJXVMap.set('anchorH', v);
						}
						v=v.val;
					}
					if (v !== anchorH) {
						anchorH = v;
						webObj=this.webObj;
						if(this._holdAttr||!webObj) {
							_poseChanged = 1;
							signUpdate();
						}else {
							webObj.style.transformOrigin=genAnchorStr();
							webObj.style.left=genXStr();
						}
					}
				},
				enumerable: true,
				configurable:true
			});

			//控件Y方向锚点位置
			Object.defineProperty(this, 'anchorV', {
				get: function () {
					return anchorV;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('anchorV');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('anchorV');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'anchorV', hudView);
							valJXVMap.set('anchorV', v);
						}
						v=v.val;
					}
					if (v !== anchorV) {
						anchorV = v;
						webObj=this.webObj;
						if(this._holdAttr||!webObj) {
							_poseChanged = 1;
							signUpdate();
						}else {
							webObj.style.transformOrigin=genAnchorStr();
							webObj.style.top=genYStr();
						}
					}
				},
				enumerable: true,
				configurable:true
			});

			//控件客户区域宽度
			Object.defineProperty(this, 'clientW', {
				get: function () {
					return this.size[0];
				},
				set: function (v) {
					return v;
				},
				enumerable: true,
				configurable:true
			});

			//控件客户区域宽度
			Object.defineProperty(this, 'clientH', {
				get: function () {
					return this.size[1];
				},
				set: function (v) {
					return v;
				},
				enumerable: true,
				configurable:true
			});

			//old dynamic w
			Object.defineProperty(this,'ofW',{
				set:function(v){
					this.w=v;
				},
				enumerable: false
			});

			//old dynamic h
			Object.defineProperty(this,'ofH',{
				set:function(v){
					this.h=v;
				},
				enumerable: false
			});

			//old dynamic x
			Object.defineProperty(this,'ofX',{
				set:function(v){
					this.x=v;
				},
				enumerable: false
			});

			//old dynamic y
			Object.defineProperty(this,'ofY',{
				set:function(v){
					this.y=v;
				},
				enumerable: false
			});

			//Layout call back
			Object.defineProperty(this, 'OnLayout', {
				get: function () {
					return this.OnLayoutFunc_;
				},
				set: function (v) {
					if (this.OnLayoutFunc_ !== v) {
						this.OnLayoutFunc_ = v;
					}
				},
				enumerable: true,
				configurable:true,
			});
			
			//Margin-Top:
			Object.defineProperty(this, 'marginT', {
				get: function () {
					return margin_t;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('marginT');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('marginT');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'marginT', hudView);
							valJXVMap.set('marginT', v);
						}
						v=v.val;
					}
					if (v!==margin_t) {
						webObj=this.webObj;
						margin_t=v;
						if(webObj) {
							webObj.style.marginTop=v+"px";
						}
					}
				},
				enumerable: true
			});
			
			//Margin-Bottom:
			Object.defineProperty(this, 'marginB', {
				get: function () {
					return margin_b;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('marginB');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('marginB');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'marginB', hudView);
							valJXVMap.set('marginB', v);
						}
						v=v.val;
					}
					if (v!==margin_b) {
						webObj=this.webObj;
						margin_b=v;
						if(webObj) {
							webObj.style.marginBottom=v+"px";
						}
					}
				},
				enumerable: true
			});

			//Margin-Left:
			Object.defineProperty(this, 'marginL', {
				get: function () {
					return margin_l;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('marginL');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('marginL');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'marginL', hudView);
							valJXVMap.set('marginL', v);
						}
						v=v.val;
					}
					if (v!==margin_l) {
						webObj=this.webObj;
						margin_l=v;
						if(webObj) {
							webObj.style.marginLeft = v + "px";
						}
					}
				},
				enumerable: true
			});
			//Margin-Right:
			Object.defineProperty(this, 'marginR', {
				get: function () {
					return margin_l;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('marginR');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('marginR');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'marginR', hudView);
							valJXVMap.set('marginR', v);
						}
						v=v.val;
					}
					if (v!==margin_r) {
						webObj=this.webObj;
						margin_r=v;
						if(webObj) {
							webObj.style.marginRight = v + "px";
						}
					}
				},
				enumerable: true
			});
		}

		//-------------------------------------------------------------------
		//可见/剪裁/颜色/放缩:
		{
			//控件是否可见，在一次Update之后才能同步
			Object.defineProperty(this, 'display', {
				get: function () {
					return display;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('display');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('display');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'display', hudView);
							valJXVMap.set('display', v);
						}
						v=v.val;
					}
					if (display !== v) {
						display = v;
						webObj=this.webObj;
						if(this._holdAttr||!webObj) {
							_poseChanged = 1;
							signUpdate();
						}else {
							if(attach) {
								switch (display) {
									case 0:
									case false:
										webObj.style.display = "none";
										break;
									case 1:
									case true:
										webObj.style.display = "block";
										break;
									case "flex-x":
									case "flex":
										webObj.style.display = "flex";
										webObj.style.flexDirection = "row";
										break;
									case "flex-y":
										webObj.style.display = "flex";
										webObj.style.flexDirection = "column";
										break;
									default:
										webObj.style.display = display;
								}
							}else {
								webObj.style.display = "none";
							}
						}
					}
				},
				enumerable: true,
				configurable:true,
			});

			//控件是否裁剪子控件:
			Object.defineProperty(this, 'clip', {
				get: function () {
					return clip;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('clip');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('clip');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'clip', hudView);
							valJXVMap.set('clip', v);
						}
						v=v.val;
					}
					if (clip !== v) {
						this.webObj;
						clip = v?1:0;
						if(this.webObj) {
							if (clip) {
								this.webObj.style.overflow="hidden";
							}else {
								this.webObj.style.overflow="visible";
							}
						}
					}
				},
				enumerable: true,
				configurable:true,
			});

			//控件的透明度
			Object.defineProperty(this,'alpha',{
				get:function(){
					return hudPose.alpha;
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('alpha');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('alpha');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'alpha', hudView);
							valJXVMap.set('alpha', v);
						}
						v=v.val;
					}
					if(v===hudPose.alpha){
						return;
					}
					hudPose.alpha=v;
					_poseChanged=1;
					signUpdate();
				},
				configurable:true,
				enumerable:true
			});

			//控件的放缩
			Object.defineProperty(this,'scale',{
				get:function(){
					return hudPose.scale;
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('scale');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('scale');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'scale', hudView);
							valJXVMap.set('scale', v);
						}
						v=v.val;
					}
					if(v===hudPose.scale){
						return;
					}
					hudPose.scale=v;
					_poseChanged=1;
					signUpdate();
				},
				configurable:true,
				enumerable:true
			});

			//控件的旋转:
			Object.defineProperty(this,'rotate',{
				get:function(){
					return hudPose.rot;
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('rotate');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('rotate');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'rotate', hudView);
							valJXVMap.set('rotate', v);
						}
						v=v.val;
					}
					if(v===hudPose.rot){
						return;
					}
					hudPose.rot=v;
					_poseChanged=1;
					signUpdate();
				},
				configurable:true,
				enumerable:true
			});

			//控件灰度化
			Object.defineProperty(this,'grayScale',{
				get:function(){
					return grayScale;
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('grayScale');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('grayScale');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'grayScale', hudView);
							valJXVMap.set('grayScale', v);
						}
						v=v.val;
					}
					v=v?1:0;
					if(v===grayScale){
						return;
					}
					grayScale=v;
					_poseChanged=1;
					signUpdate();
				},
				configurable:true,
				enumerable:true
			});
			
			//控件Filter
			Object.defineProperty(this,'filter',{
				get:function(){
					return filter;
				},
				set:function(v){
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('filter');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('filter');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'filter', hudView);
							valJXVMap.set('filter', v);
						}
						v=v.val;
					}
					if(v===filter){
						return;
					}
					filter=v;
					_poseChanged=1;
					signUpdate();
				},
				configurable:true,
				enumerable:true
			});

			//控件光标:
			Object.defineProperty(this, 'cursor', {
				get: function () {
					return cursor;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('clip');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('clip');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'clip', hudView);
							valJXVMap.set('clip', v);
						}
						v=v.val;
					}
					if (cursor !== v) {
						cursor=v;
						if(this.webObj) {
							if (cursor) {
								this.webObj.style.cursor=v;
							}else {
								this.webObj.style.cursor="auto";
							}
						}
					}
				},
				configurable:true,
				enumerable: true,
			});

		}

		//-------------------------------------------------------------------
		//控件树:
		{
			//---------------------------------------------------------------
			//父节点控件:
			Object.defineProperty(this,'father',{
				get:function(){return this.father_;},
				enumerable: false,
			});

			//---------------------------------------------------------------
			//拥有者节点控件:
			Object.defineProperty(this,'owner',{
				get:function(){return this.owner_;},
				enumerable: false,
			});

			//-------------------------------------------------------------------
			//当前控件的上一级View
			Object.defineProperty(this,"ownerView",{
				get:function(){
					var cur,nxt;
					cur=this;
					nxt=cur.father_?cur.father_:cur.owner_;
					while(nxt){
						cur=nxt;
						if(cur.isJAXHudView){
							return cur;
						}
						nxt=cur.father_?cur.father_:cur.owner_;
					}
					return null;
				},
				set:function(v){
				}
			});

			//-------------------------------------------------------------------
			//当前控件的View, 如果当前控件就是HudView，返回当前控件
			Object.defineProperty(this,"hudView",{
				get:function(){
					var cur;
					if(hudView!==undefined){
						return hudView;
					}
					cur=this;
					while(cur){
						if(cur.isJAXHudView){
							hudView=cur;
							return cur;
						}
						cur=cur.father_?cur.father_:cur.owner_;
					}
					return undefined;
				},
				set:function(v){
				}
			});

			//---------------------------------------------------------------
			//第一个子节点节点控件:
			Object.defineProperty(this,'firstChild',{
				get:function(){return this.chdHudList_[0];}
			});

			//---------------------------------------------------------------
			//得到前一个hud
			Object.defineProperty(this,'preHud',{
				get:function(){
					let father,list,idx,pre;
					father=this.father_;
					if(father){
						list=father.chdHudList_;
						idx=list.indexOf(this);
						if(idx>0){
							pre=list[idx-1];
							return pre?pre:null;
						}
					}
					return null;
				}
			});

			//---------------------------------------------------------------
			//得到后一个hud
			Object.defineProperty(this,'nextHud',{
				get:function(){
					let father,list,idx,nxt;
					father=this.father_;
					if(father){
						list=father.chdHudList_;
						idx=list.indexOf(this);
						if(idx>=0){
							nxt=list[idx+1];
							return nxt?nxt:null;
						}
					}
					return null;
				}
			});


			//---------------------------------------------------------------
			//子节点列表控件:
			Object.defineProperty(this,'items',{
				get:function(){
					return pxChdList;
				},
				set:function(list){
				},
				configurable:true
			});

		}

		//-------------------------------------------------------------------
		//交互事件:
		{
			//控件是否阻断UI的消息，在一次Update之后才能同步
			Object.defineProperty(this, 'uiEvent', {
				get: function () {
					return uiEvent;
				},
				set: function (v) {
					if(v instanceof $JXV){
						let oldV;
						oldV = valJXVMap.get('uiEvent');
						if (oldV) {
							oldV.untrace();
							valJXVMap.delete('uiEvent');
						}
						if(v.traces!==0) {
							v.trace(this.stateObj, this, 'uiEvent', hudView);
							valJXVMap.set('uiEvent', v);
						}
						v=v.val;
					}
					if (uiEvent !== v) {
						uiEvent = v;
						if(this.webObj){
							this.webObj.style.pointerEvents=v<0?"none":"auto";
						}
					}
				},
				enumerable: true,
				configurable:true,
			});

			//控件是否阻断UI的消息，在一次Update之后才能同步
			Object.defineProperty(this, 'isGenEvent', {
				get: function () {
					var hud;
					hud=this;
					while(hud){
						if(!(hud.uiEvent>0)){
							return 0;
						}
						hud=hud.father?hud.father:hud.owner;
					}
					return 1;
				},
				enumerable: false,
			});

			//控件的鼠标点击消息:
			Object.defineProperty(this, 'OnClick', {
				get: function () {
					return this.OnClickFunc_;
				},
				set: function (v) {
					var self=this;
					if (this.OnClickFunc_ !== v) {
						this.OnClickFunc_ = v;
						if (this.webObj) {
							this.webObj.onclick = v?function(e){self.OnMouseClick(e);}:null;
						}
					}
				},
				enumerable: true,
				configurable:true,
			});

			//控件的鼠标点击消息:
			Object.defineProperty(this, 'OnTreeClick', {
				get: function () {
					return this.OnTreeClickFunc_;
				},
				set: function (v) {
					var self=this;
					if (this.OnTreeClickFunc_ !== v) {
						this.OnTreeClickFunc_ = v;
						if (this.webObj) {
							this.webObj.onclick = v?function(e){self.OnMouseClick(e);}:null;
						}
					}
				},
				enumerable: true,
				configurable:true,
			});

			let WillCallInOut=0;
			let isMouseIn=0;
			let calledMouseIn=0;

			let CallMouseInOut=function(){
				//console.log("Mouse Call: "+isMouseIn+" vs "+calledMouseIn);
				if(calledMouseIn!==isMouseIn) {
					self.OnMouseInOutFunc_(isMouseIn);
					calledMouseIn=isMouseIn;
				}
				WillCallInOut=0;
			};
			let OnMouseOver=function(e)
			{
				//console.log("Mouse In");
				isMouseIn=1;
				if(!WillCallInOut){
					jaxEnv.callAfter(CallMouseInOut);
					WillCallInOut=1;
				}
			};
			let OnMouseOut=function(e)
			{
				//console.log("Mouse Out");
				isMouseIn=0;
				if(!WillCallInOut){
					jaxEnv.callAfter(CallMouseInOut);
					WillCallInOut=1;
				}
			};

			//控件鼠标移入移出的消息:
			Object.defineProperty(this, 'OnMouseInOut', {
				get: function () {
					return this.OnMouseInOutFunc_;
				},
				set: function (v) {
					if (this.OnMouseInOutFunc_ !== v) {
						this.OnMouseInOutFunc_ = v;
						if (this.webObj) {
							if(v){
								this.webObj.addEventListener('mouseover', OnMouseOver, true);
								this.webObj.addEventListener('mouseleave', OnMouseOut, true);
							}else {
								this.webObj.removeEventListener('mouseover', OnMouseOver, true);
								this.webObj.removeEventListener('mouseleave', OnMouseOut, true);
							}
						}
					}
				},
				enumerable: true,
				configurable:true,
			});
			//TODO: Code this:
		}

		//-------------------------------------------------------------------
		//Face相关:
		{
			//faces:
			Object.defineProperty(this,'faces',{
				get:function(){
					return facesVO;
				},
				set:function(v){
					if(facesVO){
						throw "Error JAXHudObj's faces can not be reset!";
					}
					facesVO=v;
					return v;
				},
				enumerable:false
			});

			//当前的face:
			Object.defineProperty(self,'face',{
				get:function(){
					return curFace;
				},
				set:function(v){
					self.showFace(v);
					return v;
				},
				enumerable:false
			});
		}
	}

	//***********************************************************************
	//不会被继承的成员函数
	//***********************************************************************
	{
		//-------------------------------------------------------------------
		//生存周期控制:
		{
			//---------------------------------------------------------------
			//增加引用，确保控件不会被提前释放:
			this.hold=function()
			{
				refCount++;
			};

			//---------------------------------------------------------------
			//减少引用，引用为0的时候，删除:
			this.release=function()
			{
				if(refCount>0) {
					refCount--;
					if (refCount === 0) {
						this._free();
					}
				}
			};

			//---------------------------------------------------------------
			//释放资源:
			this._free=function()
			{
				let hud;
				this.freeHud();
				if(this.OnFree){
					this.OnFree();
				}
				for(hud of this.chdHudList_){
					hud.release();
				}
				this.deadOut=1;
				this.chdHudList_.splice(0);
				this.webObj=null;
				//untrace记录的$JXV:
				{
					let list,val;
					list=valJXVMap.values();
					for(val of list){
						val&&val.untrace();
					}
				}
				if(this.stateObj_ && this.stateObj_.freeState){
					this.stateObj_.freeState();
					this.stateObj_=null;
				}
			};

			//---------------------------------------------------------------
			//根据CSS创建WebObj:
			this.applyCSS=function(cssObj)
			{
				JAXEnv.applyCSS(this,cssObj,JAXApp.jgxPptSet);
				if(this.OnCreate){
					this.OnCreate();
				}
				if(this.AfCreate){
					this.jaxEnv.callAfter(this.AfCreate.bind(this));
				}
			};
		}

		//-------------------------------------------------------------------
		//更新/同步WEB控件:
		{
			this._doLayout=function(){
				var owner,ow,oh,func;
				owner=this.father_||this.owner_;
				if(owner){
					ow=owner.clientW;
					oh=owner.clientH;
					if(layoutXFunc_){
						func=layoutXFunc_;
						this.x=layoutXFunc_(ow,oh);
						layoutXFunc_=func;
					}
					if(layoutYFunc_){
						func=layoutYFunc_;
						this.y=layoutYFunc_(ow,oh);
						layoutYFunc_=func;
					}
					if(layoutWFunc_){
						func=layoutWFunc_;
						this.w=layoutWFunc_(ow,oh);
						layoutWFunc_=func;
					}
					if(layoutHFunc_){
						func=layoutHFunc_;
						this.h=layoutHFunc_(ow,oh);
						layoutHFunc_=func;
					}
					if(this.OnLayoutFunc_){
						this.OnLayoutFunc_(ow,oh);
					}
					this.update();
				}
			};

			//---------------------------------------------------------------
			//如果需要更新，那就触发一次更新
			this.maybeUpdate=function()
			{
				if(isSignedUpdate){
					isSignedUpdate=0;
					this.update();
				}
			};

			//---------------------------------------------------------------
			//由JAXEnv调用的更新函数
			this._update=function()
			{
				if(isSignedUpdate) {
					isSignedUpdate = 0;
					this.update();
				}
			};

			//---------------------------------------------------------------
			//:D:Update ani:
			this._updateAni=function(){};

			//---------------------------------------------------------------
			//更新子节点:
			this.updateChildren=function()
			{
				let hud,list;
				list=this.chdHudList_;
				for(hud of list){
					hud.update();
				}
			};

			//---------------------------------------------------------------
			//当控件尺寸发生变化，调用这个函数，在这里什么都不做
			this._sizeChanged=function(){
				self.OnSizeChanged&&self.OnSizeChanged();
			};

			//---------------------------------------------------------------
			//摘除
			this.detach=function(){
				if(attach) {
					attach = 0;
					_poseChanged = 1;
					signUpdate();
				}
			};

			//---------------------------------------------------------------
			//置回:
			this.attach=function(){
				if(!attach) {
					attach = 1;
					_poseChanged = 1;
					signUpdate();
				}
			};

			//---------------------------------------------------------------
			//同步/更新WebObj的位置状态:
			this._syncWebObj=function()
			{
				let webObj,x,y,style;
				webObj=this.webObj;
				style=webObj.style;
				if(_poseChanged && webObj) {
					
					x=pos[0];
					y=pos[1];
					switch(anchorH)
					{
						case 0:
						default:
							switch(anchorV)
							{
								case 0:
									style.transformOrigin="left top";
									break;
								case 1:
									style.transformOrigin="left center";
									y-=size[1]*0.5;
									break;
								case 2:
									style.transformOrigin="left bottom";
									y-=size[1];
									break;
							}
							break;
						case 1:
							x-=size[0]*0.5;
							switch(anchorV)
							{
								case 0:
									style.transformOrigin="center top";
									break;
								case 1:
									style.transformOrigin="center center";
									y-=size[1]*0.5;
									break;
								case 2:
									style.transformOrigin="center bottom";
									y-=size[1];
									break;
							}
							break;
						case 2:
							x-=size[0];
							switch(anchorV)
							{
								case 0:
									style.transformOrigin="right top";
									break;
								case 1:
									style.transformOrigin="right center";
									y-=size[1]*0.5;
									break;
								case 2:
									style.transformOrigin="right bottom";
									y-=size[1];
									break;
							}
							break;
					}
					style.left=""+x+"px";
					style.top=""+y+"px";
					style.width=""+size[0]+"px";
					style.height=""+size[1]+"px";
					
					if(hudPose.scale!==1.0){
						if(hudPose.rot!==0){
							style.transform="scale("+hudPose.scale+") rotate("+(hudPose.rot)+"deg)";
						}else {
							style.transform="scale("+hudPose.scale+") rotate(0deg)";
						}
					}else {
						if(hudPose.rot!==0){
							style.transform="rotate("+(hudPose.rot)+"deg)";
						}else {
							style.transform="";
						}
					}
					//style.display=(this.display&&attach)?"block":"none";
					if(attach) {
						switch (display) {
							case 0:
							case false:
								style.display = "none";
								break;
							case 1:
							case true:
								style.display = "block";
								break;
							case "flex-x":
							case "flex":
								webObj.style.display = "flex";
								webObj.style.flexDirection = "row";
								break;
							case "flex-y":
								webObj.style.display = "flex";
								webObj.style.flexDirection = "column";
								break;
							default:
								style.display = display;
						}
					}else {
						style.display = "none";
					}
					
					
					if(filter){
						style.filter = filter;
					}else if(grayScale){
						style.filter = "grayscale(1)";
					}else {
						style.filter = "";
					}
					style.opacity=""+hudPose.alpha;
					_poseChanged=0;
				}
				if(size[0]!==oldW || size[1]!==oldH){
					let list,i,n,chd;
					oldW=size[0];
					oldH=size[1];
					list=this.chdHudList_;
					n=list.length;
					for(i=0;i<n;i++){
						chd=list[i];
						if(chd.autoLayout){
							chd._doLayout();
						}
					}
					this._sizeChanged();
					if(this.OnResize){
						this.OnResize();
					}
				}
			};
		}

		//-------------------------------------------------------------------
		//控件树:
		{
			//---------------------------------------------------------------
			this._applyItems=function(list)
			{
				let css,hud;
				this.removeAllChildren();
				for(css of list){
					hud=JAXHudObj.createHudByType(css.type,this.jaxEnv,this,css);
					if(hud){
						hud.release();
					}
				}
			};

			//---------------------------------------------------------------
			//通过CSS添加一个新子节点
			this.appendNewChild = function (css)
			{
				let hud=JAXHudObj.createHudByType(css.type,this.jaxEnv,this,css);
				if(hud){
					hud.release();
				}
				signUpdate();
				return hud;
			};

			//---------------------------------------------------------------
			//通过CSS插入一个子节点
			this.insertNewChild = function (css,beforeHud)
			{
				let hud=JAXHudObj.createHudByType(css.type,this.jaxEnv,this,css);
				if(hud){
					if(beforeHud){
						this.removeChild(hud);
						this.insertBefore(hud,beforeHud);
					}
					hud.release();
				}
				signUpdate();
				return hud;
			};


			//---------------------------------------------------------------
			//添加一个子节点
			this.appendChild = function (hud)
			{
				var view;
				if (hud.father_) {
					throw "Error: 控件已有父节点，不能添加至当前节点."
				}
				view=hud.hudView;
				if(view!==undefined && view!==this.hudView && view!==hud){
					throw "Error: 控件不能绑定不同的View."
				}
				hud.father_ = this;
				hud.hold();
				this.chdHudList_.push(hud);
				//Link webObjs:
				if(hud.webObj && this.webObj){
					this.webObj.appendChild(hud.webObj);
				}
				if(hud.autoLayout){
					hud._doLayout();
				}
				signUpdate();
			};

			//-------------------------------------------------------------------
			//添加一个子节点
			this.insertBefore = function (hud, chd)
			{
				let list, i, n;
				if (hud.father_) {
					throw "Error: 控件已有父节点，不能添加至当前节点"
				}
				if (chd.father_ !== this) {
					throw "Error: 控件的父节点不是当前控件，不能插入子节点。"
				}
				list = this.chdHudList_;
				n = list.length;
				findChd:{
					for (i = 0; i < n; i++) {
						if (list[i] === chd) {
							list.splice(i, 0, hud);
							hud.hold();
							break findChd;
						}
					}
				}
				hud.father_ = this;
				//Link webObjs:
				if(hud.webObj && this.webObj && chd.webObj){
					this.webObj.insertBefore(hud.webObj,chd.webObj);
				}
				if(hud.autoLayout){
					hud._doLayout();
				}
				signUpdate();
			};

			//-------------------------------------------------------------------
			//删除一个子节点
			this.removeChild = function (hud)
			{
				let list, i,hudWebObj;
				if (hud.father_ !== this) {
					throw "Error: 控件的父节点不是当前控件，不能删除子节点。"
				}
				hud.father_ = null;
				list = this.chdHudList_;
				i=list.indexOf(hud);
				if(i>=0){
					list.splice(i,1);
					hudWebObj=hud.webObj;
					if(hudWebObj && hudWebObj.parentElement){
						hudWebObj.parentElement.removeChild(hudWebObj);
					}
					//hud.webObj=null;
					/*if(this.webObj && hud.webObj){
						this.webObj.removeChild(hud.webObj);
					}*/
					hud.release();
				}
				signUpdate();
			};

			//-------------------------------------------------------------------
			//查找一个子节点的序号
			this.getChildHudIdx = function (hud2Find) {
				let list;
				list=this.chdHudList_;
				return list.indexOf(hud2Find);
				/*
				n=list.length;
				for(i=0;i<n;i++){
					if(list[i]===hud2Find){
						return i;
					}
				}
				return -1;*/
			};

			//-------------------------------------------------------------------
			//查找一个子节点
			this.findHudById = function (id2Find)
			{
				let hud, fnd;
				if (id2Find === id) {
					return this;
				}
				let list, i, n;
				list = this.chdHudList_;
				n = list.length;
				for (i = 0; i < n; i++) {
					hud = list[i];
					fnd = hud.findHudById(id2Find);
					if (fnd)
						return fnd;
				}
				return null;
			};

			//-------------------------------------------------------------------
			//查找一个子节点
			this.findObjById = function (id2Find)
			{
				let hud, fnd;
				if (id2Find === id) {
					return this;
				}
				let list, i, n;
				list = this.chdHudList_;
				n = list.length;
				for (i = 0; i < n; i++) {
					hud = list[i];
					fnd = hud.findObjById(id2Find);
					if (fnd)
						return fnd;
				}
				return null;
			};

			//-------------------------------------------------------------------
			//删除全部子节点
			this.removeAllChildren = function ()
			{
				let list, hud,hudWebObj;
				list = this.chdHudList_;
				for (hud of list) {
					hudWebObj=hud.webObj;
					if(hudWebObj && hudWebObj.parentElement){
						hudWebObj.parentElement.removeChild(hudWebObj);
					}
					//hud.webObj=null;
					/*if(webObj && hudWebObj){
						webObj.removeChild(hudWebObj);
					}*/
					hud.father_=null;
					hud.release();
				}
				list.splice(0);
				signUpdate();
			};

			//-------------------------------------------------------------------
			//在全部子节点（包含subs）里执行一个函数:
			this.execInTree=function(func){
				var list,i,n;
				list=this.chdHudList_;
				n=list.length;
				for(i=0;i<n;i++){
					if(func(list[i])){
						return;
					}
				}
			};
		}

		//-------------------------------------------------------------------
		//坐标转换:
		{
			//---------------------------------------------------------------
			//得到相对于某控件的坐标:
			this.findRelatedPos=function(x,y,hud=null){
				var tgtDiv,curDiv,hudObj,dx,dy,scale;
				tgtDiv=hud?hud.webObj:window.document.body;//this.jaxEnv.jaxDiv;
				curDiv=this.webObj;
				
				if(curDiv.offsetParent){
					let cRect=curDiv.getBoundingClientRect();
					let tRect=tgtDiv.getBoundingClientRect();
					hudObj=curDiv.jaxObj;
					dx=cRect.x-tRect.x;
					dy=cRect.y-tRect.y;
					switch(hudObj.anchorH){
						case 0:
							break;
						case 1:
							dx+=hudObj.w*0.5;
							break;
						case 2:
							dx+=hudObj.w;
							break;
					}
					switch(hudObj.anchorV){
						case 0:
							break;
						case 1:
							dy+=hudObj.h*0.5;
							break;
						case 2:
							dy+=hudObj.h;
							break;
					}
					return [x+dx,y+dy];
				}
				
				if(curDiv && curDiv!==tgtDiv){
					hudObj=curDiv.jaxObj;
					if(hudObj){
						hudObj.maybeUpdate();
						dx=hudObj.x;
						dy=hudObj.y;
						scale=hudObj.scale;
						x+=dx;
						y+=dy;
					}else {
						dx=curDiv.offsetLeft;
						dy=curDiv.offsetTop;
						x+=dx;
						y+=dy;
					}
					curDiv=curDiv.offsetParent||curDiv.parentNode;
				}
				while(curDiv && curDiv!==tgtDiv){
					hudObj=curDiv.jaxObj;
					if(hudObj){
						hudObj.maybeUpdate();
						scale=hudObj.scale;
						switch(hudObj.anchorH){
							case 0:
								dx=0;
								break;
							case 1:
								dx=-hudObj.w*0.5;
								break;
							case 2:
								dx=-hudObj.w;
								break;
						}
						switch(hudObj.anchorV){
							case 0:
								dy=0;
								break;
							case 1:
								dy=-hudObj.h*0.5;
								break;
							case 2:
								dy=-hudObj.h;
								break;
						}
						dx*=scale;dy*=scale;
						dx+=hudObj.x+curDiv.clientLeft*scale;
						dy+=hudObj.y+curDiv.clientTop*scale;
						x=x*scale+dx;
						y=y*scale+dy;
					}else {
						dx=curDiv.offsetLeft+curDiv.clientLeft;
						dy=curDiv.offsetTop+curDiv.clientTop;
						x+=dx;
						y+=dy;
					}
					curDiv=curDiv.offsetParent||curDiv.parentNode;
				}
				return [x,y];
			};
		}

		//-------------------------------------------------------------------
		//Ani控制:
		{
			//---------------------------------------------------------------
			//播放一个/多个动画:
			this.animate=function(def,play=1){
				let ani;
				if(Array.isArray(def)){
					let anis=[];
					for(let subDef of def){
						anis.push(this.animate(subDef,play));
					}
					return anis;
				}
				ani=JAXAni.createAniByType(def.type,jaxEnv,def,this);
				if(play) {
					ani.start();
				}
				return ani;
			};
		}

		//-------------------------------------------------------------------
		//Faces:
		{
			//---------------------------------------------------------------
			//展示一个Face
			this.showFace=function(faceName,vo)
			{
				var faceVO,showFunc,oldFace;
				if(!facesVO){
					return;
				}
				//如果是数组，对每一项执行showFace
				if(Array.isArray(faceName)){
					for(let subName of faceName){
						this.showFace(subName,null);
					}
					return;
				}
				faceVO=typeof(faceName)==='string'?facesVO[faceName]:faceName;
				if(!faceVO){
					//throw "Face not found: "+faceName;
					return;
				}
				showFunc=typeof(faceVO)==='function'?faceVO:faceVO.show;
				if(!showFunc){
					//faceVO就是AttrVO:
					this._applyFaceVO(faceVO,vo);
					return;
				}
				showFunc(this,vo,oldFace);
			};

			//---------------------------------------------------------------
			//切换至一个Face
			this.switchFace=function(faceName,vo)
			{
				var faceVO,showFunc,oldFace;

				if(!this.faces){
					return;
				}
				faceVO=typeof(faceName)==='string'?this.faces[faceName]:faceName;
				if(!faceVO){
					//console.log("Face not found: "+faceName);
					return;
				}

				oldFace=curFace;
				if(curFaceVO && curFaceVO.hide){
					curFaceVO.hide(faceName);
				}

				showFunc=typeof(faceVO)==='function'?faceVO:faceVO.show;

				curFaceVO=faceVO;
				curFace=faceName;
				if(!showFunc){
					//faceVO就是AttrVO:
					this._applyFaceVO(faceVO,vo);
					return;
				}
				showFunc(this,vo,oldFace);
			};

			//---------------------------------------------------------------
			//应用Face的属性列表:
			this._applyFaceVO=function(faceVO,vo){
				let itemId,hudId,hud,attrs,attrName,attr,val,attrType,tgtObj;
				if(Array.isArray(faceVO)){
					let vo;
					for(vo of faceVO){
						this._applyFaceVO(vo);
					}
					return;
				}
				if(typeof(faceVO)==='function'){
					faceVO.call(this,vo);
					return;
				}
				for(itemId in faceVO){
					hudId=itemId;
					attrs=faceVO[hudId];
					attrType=typeof(attrs);
					if(attrType==="function") {
						attrs.call(this,vo);
					}else if(hudId.startsWith("@")){
						let time,self;
						//FaceTime:
						self=this;
						time=parseInt(hudId.substring(1));
						if(time>0){
							window.setTimeout(()=>{
								self._applyFaceVO(attrs);
							},time);
						}
					}else {
						if (hudId in this) {
							hud = this[hudId];
						} else {
							hud = this[hudId] = this.findObjById(hudId);
						}
						if (hud) {
							let anis;
							if(attrs===0){
								hud.display = 0;
							}else if(attrs===1) {
								hud.display = 1;
							}else {
								anis=attrs.ani;
								if(anis){
									anis=hud.animate(anis,0);
								}
								for (attrName in attrs) {
									attr = attrName;
									val = attrs[attr];
									attrType = typeof (val);
									if(attr!=="ani"){
										if (attr.startsWith("%")) {
											tgtObj = hud.hudState || hud.stateObj_ || hud;
											attr = attr.substring(1);
										} else {
											tgtObj = hud;
										}
										if (val !== undefined) {
											if(val instanceof Function){
												tgtObj[attr] = val.call(self);
											}else {
												tgtObj[attr] = val;
											}
										}
									}
								}
								if(anis){
									if(anis instanceof JAXAni){
										anis.start();
									}else {
										for(let ani of anis){
											ani.start();
										}
									}
								}
							}
						}
					}
				}
			};

			//TODO: Code this:
		}
	}
};

JAXHudObj.prototype=__Proto$h;


//***************************************************************************
//静态Class成员函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudObj.jaxPptSet=new Set([
		'id','jaxObjHash','jaxId',
		'autoLayout',
		'position','x','y','w','h','anchorH','anchorV',"zIndex",
		'ofX','ofY','ofW','ofH',
		'marginT','marginB','marginL','marginR',
		'display','clip','alpha','filter','scale','rotate','cursor',
		'uiEvent','items',
		'OnLayout','OnClick','OnTreeClick','OnMouseInOut',
		'faces'
	]);
	var HudTypeHash = {};

	//---------------------------------------------------------------------------
	//注册Hud控件类型
	JAXHudObj.regHudByType = function (typeName, func) {
		HudTypeHash[typeName] = func;
	};

	//---------------------------------------------------------------------------
	//根据类型创建Hud控件
	JAXHudObj.createHudByType = function (typeName, env, father,css,owner) {
		let typeType,func,hud,obj;
		if(css.skipCreate){
			return null;
		}
		typeType=typeof(typeName);
		if(typeType==="string") {
			func = HudTypeHash[typeName];
		}
		if(!func){
			obj=css;
			while(typeof(obj)==="object"){
				func = HudTypeHash[obj.type];
				if (func) {
					break;
				}
				obj=obj.css||obj.type;
			}
			if(!func) {
				console.error("JAXError hud-type '" + typeName + "' has no creator function.");
				return null;
			}
		}
		hud=func(env);
		if(hud){
			if(father){
				father.appendChild(hud);
			}else if(owner){
				owner.appendChild(hud);
				hud.owner_=owner;
			}
			if(css) {
				JAXEnv.applyCSS(hud,css);
			}
			if(typeof(hud.OnCreate)==='function'){
				hud.OnCreate();
			}
			if(typeof(hud.AfCreate)==='function'){
				hud.jaxEnv.callAfter(hud.AfCreate.bind(hud));
			}
			//应该在这里弹出HashObj:
			hud.jaxEnv.popObjHasher(hud);
			if(owner){
				owner.removeChild(hud);
			}
		}
		return hud;
	};

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('hud', function (env) {
		return new JAXHudObj(env);
	});
	JAXHudObj.regHudByType('item', function (env) {
		return new JAXHudObj(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS合并属性之前，创建WebObj:
	__Proto$h.preApplyCSS = function (cssObj)
	{
		var div,father,jaxEnv,owner,ownerState;
		jaxEnv=this.jaxEnv;
		this.removeAllChildren();
		father = this.father;
		owner = this.owner;
		if(!this.webObj) {
			div = this.webObj = document.createElement(this.webObjTag);
			div.style.position = cssObj.position||"absolute";
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj=this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;

			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS把pptList赋值后
	__Proto$h.finApplyCSS = function (cssObj)
	{
		if(this.webObj){
			this.webObj.id=this.id;
		}
		this.items2Add_=cssObj.items;
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$h.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		delete this.items2Add_;
		if(cssObj.face){
			this.showFace(cssObj.face);
		}

		this._syncWebObj();
		this._holdAttr=false;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$h.update=function()
	{
		let webObj;

		webObj=this.webObj;
		//if(webObj && this.poseChanged) {
		if(webObj) {
			this._syncWebObj();
		}
	};

	//---------------------------------------------------------------
	//控件被点击消息:
	__Proto$h.OnMouseClick=function(e)
	{
		if(this.isGenEvent){
			if(e.srcElement===this.webObj && this.OnClickFunc_) {
				e.stopPropagation();
				this.OnClickFunc_.call(this, e);
			}else if(this.OnTreeClickFunc_){
				e.stopPropagation();
				this.OnTreeClickFunc_.call(this, e);
			}
		}
	};

	//-----------------------------------------------------------------------
	//释放资源:
	__Proto$h.freeHud=function(){
		var father,div;
		this.removeAllChildren();
		father=this.father;
		div=this.webObj;
		if(div && father && father.webObj){
			father=div.parentNode;
			if(father){
				father.removeChild(div);
			}
			this.webObj=null;
		}
	};
}

var JAXHudView,__Proto$g;

JAXHudView=function(jaxEnv)
{
	var statesInView=[];
	var allowValNotify=true;
	var self=this;

	if(!jaxEnv){
		return;
	}
	JAXHudObj.call(this,jaxEnv);

	self.isJAXHudView=true;

	//***********************************************************************
	//属性/数据链接相关
	//***********************************************************************
	{
		//-------------------------------------------------------------------
		//当前View是否允许valNotify
		Object.defineProperty(this,"allowValNotify",{
			get:function(){
				var ownerView;
				if(!allowValNotify)
					return false;
				ownerView=this.ownerView;
				return ownerView?ownerView.allowValNotify:true;
			},
			set:function(v){
				v=v?true:false;
				if(v!==allowValNotify){
					allowValNotify=v;
					if(v && self.stateObj){
						self.stateObj.update();
					}
				}
			}
		});

		//-------------------------------------------------------------------
		//增加View绑定的HudState
		this.addHudState=function(state){
			statesInView.push(state);
		};

		//-------------------------------------------------------------------
		//更新当前View下面的全部链接
		this.updateStates=function(){
			var state;
			for(state of statesInView){
				state.updateState();
			}
		};
	}
};

__Proto$g=JAXHudView.prototype=new JAXHudObj();

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudView.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'allowValNotify'
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('view', function (env) {
		return new JAXHudView(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的最后，创建WebObj:
	__Proto$g.preApplyCSS = function (cssObj) {
		var div, father, stateObj;
		let jaxEnv=this.jaxEnv;

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		this.removeAllChildren();
		if (!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText +=style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if (cssObj.faces) {
			cssObj.jaxObjHash = 1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		this.jaxEnv.pushHudView(this);
		//确定StateObj:
		stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS把pptList赋值后
	__Proto$g.finApplyCSS = function (cssObj) {
		if (this.webObj) {
			this.webObj.id = this.id;
		}
		this.items2Add_ = cssObj.items;
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$g.postApplyCSS = function (cssObj) {
		let list;
		list = this.items2Add_;
		if (Array.isArray(list)) {
			this._applyItems(list);
		}
		this.items2Add_ = null;

		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }

		this.jaxEnv.popHudView(this);
	};
}

var JAXHudLayer;

JAXHudLayer=function(app,appDiv)
{
	var div,dockDiv,self,attached;
	var uiEvent;
	if(!app){
		return;
	}
	JAXHudView.call(this,app.jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	self=this;

	uiEvent=1;

	this.jaxClassFunc=JAXHudLayer;
	//***********************************************************************
	//属性定义
	//***********************************************************************
	{
		//控件是否阻断UI的消息，在一次Update之后才能同步
		Object.defineProperty(this, 'uiEvent', {
			get: function () {
				return uiEvent;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('uiEvent');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('uiEvent');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'uiEvent', hudView);
						valJXVMap.set('uiEvent', v);
					}
					v=v.val;
				}
				if (uiEvent !== v) {
					uiEvent = v;
					if(this.dockWebObj){
						this.dockWebObj.style.pointerEvents=v<0?"none":"auto";
					}
				}
			},
			enumerable: true,
			configurable:true,
		});
	}
	this.dockWebObj=dockDiv=document.createElement('div');
	dockDiv.style.position="absolute";
	dockDiv.style.left="0px";
	dockDiv.style.top="0px";
	dockDiv.style.width="100%";
	dockDiv.style.height="100%";
	appDiv.appendChild(dockDiv);

	this.webObj=div=document.createElement('div');
	div.style.position="absolute";
	this.w=appDiv.offsetWidth;
	this.h=appDiv.offsetHeight;
	dockDiv.appendChild(div);
	attached=1;

	//-----------------------------------------------------------------------
	//Layer脱离控件树:
	self.detachLayer=function(){
		if(!attached){
			return;
		}
		dockDiv.removeChild(div);
		dockDiv.style.display="none";
		attached=0;
	};

	//-----------------------------------------------------------------------
	//Layer并入控件树:
	self.attachLayer=function(){
		if(attached){
			return;
		}
		dockDiv.appendChild(div);
		dockDiv.style.display="";
		attached=1;
	};

};

JAXHudLayer.prototype=new JAXHudView();

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudLayer.jaxPptSet = new Set(['id','x','y','w','h','ofX','ofY','ofW','ofH','uiEvent','items']);
}

var JAXApp,__Proto$f;

JAXApp=function(jaxEnv,appDiv){
	if(!jaxEnv)
		return;
	JAXDataObj.call(this,jaxEnv,null,null);

	this.appPath=document.location.pathname;
	this.appDir=JAXEnv.getPathDir(this.appPath);
	this.jaxClassFunc=JAXApp;

	this.jaxEnv=jaxEnv;
	this.appDiv=appDiv;
	this.clientW=this.w=appDiv.offsetWidth;
	this.clientH=this.h=appDiv.offsetHeight;
	this.layers_=[];

	this.uiEvent=1;

	Object.defineProperty(this,'layers',{
		set:function(list){
			let layerCSS,layer;
			for(layerCSS of list){
				layer=new JAXHudLayer(this,appDiv);
				layer.owner_=this;
				layer.applyCSS(layerCSS);
				this.layers_.push(layer);
			}
		}
	});

	//可能会用到的回调函数:
	//this.OnCreate=null;
	//this.OnFree=null;
	//this.AfCreate=null;
};

JAXApp.jaxPptSet=new Set(["layers"]);

__Proto$f=JAXApp.prototype={};

//---------------------------------------------------------------------------
//根据CSS创建App
__Proto$f.startByDef=function(cssObj)
{
	this.jaxEnv.pushObjHasher(this);
	JAXEnv.applyCSS(this,cssObj,JAXApp.jgxPptSet);
	if(this.OnCreate){
		this.OnCreate();
	}
	if(this.AfCreate){
		this.jaxEnv.callAfter(this.AfCreate.bind(this));
	}
	this.jaxEnv.popObjHasher(this);
};

//---------------------------------------------------------------------------
//根据CSS创建App
__Proto$f.update=function()
{
	/*let list,layer;
	list=this.layers_;
	for(layer of list){
		layer.update();
	}*/
	//TODO: Code this:
};

//---------------------------------------------------------------------------
//网页窗口尺寸发生变化:
__Proto$f.OnResize=function(w,h){
	var style=this.appDiv.style;
	var list,i,n;
	this.w=w;
	this.h=h;
	style.width=""+w+"px";
	style.height=""+h+"px";
	this.w=w;
	this.h=h;
	this.clientW=w;
	this.clientH=h;
	list=this.layers_;
	n=list.length;
	for(i=0;i<n;i++){
		list[i]._doLayout();
	}
};

//---------------------------------------------------------------
//ApplyCSS合并属性之前
__Proto$f.preApplyCSS = function (cssObj){
	var stateObj=cssObj.appState;
	if(stateObj){
		if(!stateObj.isJAXHudState) {
			stateObj = jaxHudState(this.jaxEnv, stateObj);
		}
		this.jaxEnv.pushHudState(stateObj);
		this.stateObj=stateObj;
		this.stateObj_=stateObj;
		stateObj.setupState();
	}
};

//---------------------------------------------------------------
//ApplyCSS的最后:
__Proto$f.postApplyCSS = function (cssObj) {
	let stateObj=this.stateObj_;
	if(stateObj){
		this.jaxEnv.popHudState(stateObj);
	}

};


//***************************************************************************
//有关启动App的函数:
//***************************************************************************
{
	__Proto$f=JAXEnv.prototype;
	//---------------------------------------------------------------------------
	//创建App
	__Proto$f.createApp=function()
	{
		if(this.app){
			throw "Error: JAXEnv already has a App!";
		}
		this.app=new JAXApp(this,this.jaxDiv);
		return this.app;
	};

	//---------------------------------------------------------------------------
	//初始化App
	__Proto$f.initApp=function(appDef)
	{
		if(!this.app){
			throw "Error: JAXEnv has no App!";
		}
		this.app.startByDef(appDef);
		return this.app;
	};

	//---------------------------------------------------------------------------
	//创建且初始化App
	__Proto$f.startApp=function(appDef)
	{
		this.app=new JAXApp(this,this.jaxDiv);
		this.app.startByDef(appDef);
		return this.app;
	};
}

class JAXDiskSysStore {
	constructor() {
		let dbName,storeName;
		dbName="CokeCodes";
		storeName="System";
		this.storeName = storeName;
		this._dbp = new Promise((resolve, reject) => {
			const openreq = indexedDB.open(dbName, 1);
			openreq.onerror = () => reject(openreq.error);
			openreq.onsuccess = () => resolve(openreq.result);
			// First time setup: create an empty object store
			openreq.onupgradeneeded = () => {
				openreq.result.createObjectStore(storeName);
			};
		});
	}
	_withIDBStore(type, callback) {
		return this._dbp.then(db => new Promise((resolve, reject) => {
			const transaction = db.transaction(this.storeName, type);
			transaction.oncomplete = () => resolve();
			transaction.onabort = transaction.onerror = () => reject(transaction.error);
			callback(transaction.objectStore(this.storeName));
		}));
	}
}
let sysStore=null;

class JAXDiskStore {
	constructor(diskName, storeName = null) {
		let dbName;
		dbName="Disk_"+diskName;
		this.dbName=dbName;
		storeName=storeName||diskName;
		if(storeName!==diskName && storeName!=="info" && storeName!=="base"){
			throw Error("JAXDiskStore: Store name error: "+storeName);
		}
		this.storeName = storeName;
		this._dbp = new Promise((resolve, reject) => {
			const openreq = indexedDB.open(dbName, 1);
			openreq.onerror = () => reject(openreq.error);
			openreq.onsuccess = () => resolve(openreq.result);
			// First time setup: create an empty object store
			openreq.onupgradeneeded = () => {
				openreq.result.createObjectStore(diskName);
				openreq.result.createObjectStore("info");
				openreq.result.createObjectStore("base");
			};
		});
	}
	_withIDBStore(type, callback) {
		return this._dbp.then(db => new Promise((resolve, reject) => {
			const transaction = db.transaction(this.storeName, type);
			transaction.oncomplete = () => resolve();
			transaction.onabort = transaction.onerror = () => reject(transaction.error);
			callback(transaction.objectStore(this.storeName));
		}));
	}
	static systemStore(){
		if(sysStore){
			return sysStore;
		}
		sysStore=new JAXDiskSysStore();
		return sysStore;
	}
}

function get$1(key, store) {
	let req;
	return store._withIDBStore('readonly', store => {
		req = store.get(key);
	}).then(() => req.result);
}
function set$1(key, value, store) {
	return store._withIDBStore('readwrite', store => {
		store.put(value, key);
	});
}
function del(key, store) {
	return store._withIDBStore('readwrite', store => {
		store.delete(key);
	});
}
function clear(store) {
	return store._withIDBStore('readwrite', store => {
		store.clear();
	});
}
function keys(store) {
	const keys = [];
	return store._withIDBStore('readonly', store => {
		// This would be store.getAllKeys(), but it isn't supported by Edge or Safari.
		// And openKeyCursor isn't supported by Safari.
		(store.openKeyCursor || store.openCursor).call(store).onsuccess = function () {
			if (!this.result)
				return;
			keys.push(this.result.key);
			this.result.continue();
		};
	}).then(() => keys);
}

function drop(databaseName){
	indexedDB.deleteDatabase(databaseName);
}

//>>>>>>Node2Coke>>>>>>
var module$1$1={exports:{}};
var module$2=module$1$1;

function assertPath(path) {
	if (typeof path !== 'string') {
		throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
	}
}

// Resolves . and .. elements in a path with directory names
function normalizeStringPosix(path, allowAboveRoot) {
	var res = '';
	var lastSegmentLength = 0;
	var lastSlash = -1;
	var dots = 0;
	var code;
	for (var i = 0; i <= path.length; ++i) {
		if (i < path.length)
			code = path.charCodeAt(i);
		else if (code === 47 /*/*/)
			break;
		else
			code = 47 /*/*/;
		if (code === 47 /*/*/) {
			if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) {
				if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
					if (res.length > 2) {
						var lastSlashIndex = res.lastIndexOf('/');
						if (lastSlashIndex !== res.length - 1) {
							if (lastSlashIndex === -1) {
								res = '';
								lastSegmentLength = 0;
							} else {
								res = res.slice(0, lastSlashIndex);
								lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
							}
							lastSlash = i;
							dots = 0;
							continue;
						}
					} else if (res.length === 2 || res.length === 1) {
						res = '';
						lastSegmentLength = 0;
						lastSlash = i;
						dots = 0;
						continue;
					}
				}
				if (allowAboveRoot) {
					if (res.length > 0)
						res += '/..';
					else
						res = '..';
					lastSegmentLength = 2;
				}
			} else {
				if (res.length > 0)
					res += '/' + path.slice(lastSlash + 1, i);
				else
					res = path.slice(lastSlash + 1, i);
				lastSegmentLength = i - lastSlash - 1;
			}
			lastSlash = i;
			dots = 0;
		} else if (code === 46 /*.*/ && dots !== -1) {
			++dots;
		} else {
			dots = -1;
		}
	}
	return res;
}

function _format(sep, pathObject) {
	var dir = pathObject.dir || pathObject.root;
	var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
	if (!dir) {
		return base;
	}
	if (dir === pathObject.root) {
		return dir + base;
	}
	return dir + sep + base;
}

var posix = {
	// path.resolve([from ...], to)
	resolve: function resolve() {
		var resolvedPath = '';
		var resolvedAbsolute = false;
		var cwd;
		
		for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
			var path;
			if (i >= 0)
				path = arguments[i];
			else {
				if (cwd === undefined)
					cwd = process.cwd();
				path = cwd;
			}
			
			assertPath(path);
			
			// Skip empty entries
			if (path.length === 0) {
				continue;
			}
			
			resolvedPath = path + '/' + resolvedPath;
			resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
		}
		
		// At this point the path should be resolved to a full absolute path, but
		// handle relative paths to be safe (might happen when process.cwd() fails)
		
		// Normalize the path
		resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
		
		if (resolvedAbsolute) {
			if (resolvedPath.length > 0)
				return '/' + resolvedPath;
			else
				return '/';
		} else if (resolvedPath.length > 0) {
			return resolvedPath;
		} else {
			return '.';
		}
	},
	
	normalize: function normalize(path) {
		assertPath(path);
		
		if (path.length === 0) return '.';
		
		var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
		var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;
		
		// Normalize the path
		path = normalizeStringPosix(path, !isAbsolute);
		
		if (path.length === 0 && !isAbsolute) path = '.';
		if (path.length > 0 && trailingSeparator) path += '/';
		
		if (isAbsolute) return '/' + path;
		return path;
	},
	
	isAbsolute: function isAbsolute(path) {
		assertPath(path);
		return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
	},
	
	join: function join() {
		if (arguments.length === 0)
			return '.';
		var joined;
		for (var i = 0; i < arguments.length; ++i) {
			var arg = arguments[i];
			assertPath(arg);
			if (arg.length > 0) {
				if (joined === undefined)
					joined = arg;
				else
					joined += '/' + arg;
			}
		}
		if (joined === undefined)
			return '.';
		return posix.normalize(joined);
	},
	
	relative: function relative(from, to) {
		assertPath(from);
		assertPath(to);
		
		if (from === to) return '';
		
		from = posix.resolve(from);
		to = posix.resolve(to);
		
		if (from === to) return '';
		
		// Trim any leading backslashes
		var fromStart = 1;
		for (; fromStart < from.length; ++fromStart) {
			if (from.charCodeAt(fromStart) !== 47 /*/*/)
				break;
		}
		var fromEnd = from.length;
		var fromLen = fromEnd - fromStart;
		
		// Trim any leading backslashes
		var toStart = 1;
		for (; toStart < to.length; ++toStart) {
			if (to.charCodeAt(toStart) !== 47 /*/*/)
				break;
		}
		var toEnd = to.length;
		var toLen = toEnd - toStart;
		
		// Compare paths to find the longest common path from root
		var length = fromLen < toLen ? fromLen : toLen;
		var lastCommonSep = -1;
		var i = 0;
		for (; i <= length; ++i) {
			if (i === length) {
				if (toLen > length) {
					if (to.charCodeAt(toStart + i) === 47 /*/*/) {
						// We get here if `from` is the exact base path for `to`.
						// For example: from='/foo/bar'; to='/foo/bar/baz'
						return to.slice(toStart + i + 1);
					} else if (i === 0) {
						// We get here if `from` is the root
						// For example: from='/'; to='/foo'
						return to.slice(toStart + i);
					}
				} else if (fromLen > length) {
					if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
						// We get here if `to` is the exact base path for `from`.
						// For example: from='/foo/bar/baz'; to='/foo/bar'
						lastCommonSep = i;
					} else if (i === 0) {
						// We get here if `to` is the root.
						// For example: from='/foo'; to='/'
						lastCommonSep = 0;
					}
				}
				break;
			}
			var fromCode = from.charCodeAt(fromStart + i);
			var toCode = to.charCodeAt(toStart + i);
			if (fromCode !== toCode)
				break;
			else if (fromCode === 47 /*/*/)
				lastCommonSep = i;
		}
		
		var out = '';
		// Generate the relative path based on the path difference between `to`
		// and `from`
		for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
			if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
				if (out.length === 0)
					out += '..';
				else
					out += '/..';
			}
		}
		
		// Lastly, append the rest of the destination (`to`) path that comes after
		// the common path parts
		if (out.length > 0)
			return out + to.slice(toStart + lastCommonSep);
		else {
			toStart += lastCommonSep;
			if (to.charCodeAt(toStart) === 47 /*/*/)
				++toStart;
			return to.slice(toStart);
		}
	},
	
	_makeLong: function _makeLong(path) {
		return path;
	},
	
	dirname: function dirname(path) {
		assertPath(path);
		if (path.length === 0) return '.';
		var code = path.charCodeAt(0);
		var hasRoot = code === 47 /*/*/;
		var end = -1;
		var matchedSlash = true;
		for (var i = path.length - 1; i >= 1; --i) {
			code = path.charCodeAt(i);
			if (code === 47 /*/*/) {
				if (!matchedSlash) {
					end = i;
					break;
				}
			} else {
				// We saw the first non-path separator
				matchedSlash = false;
			}
		}
		
		if (end === -1) return hasRoot ? '/' : '.';
		if (hasRoot && end === 1) return '//';
		return path.slice(0, end);
	},
	
	basename: function basename(path, ext) {
		if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
		assertPath(path);
		
		var start = 0;
		var end = -1;
		var matchedSlash = true;
		var i;
		
		if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
			if (ext.length === path.length && ext === path) return '';
			var extIdx = ext.length - 1;
			var firstNonSlashEnd = -1;
			for (i = path.length - 1; i >= 0; --i) {
				var code = path.charCodeAt(i);
				if (code === 47 /*/*/) {
					// If we reached a path separator that was not part of a set of path
					// separators at the end of the string, stop now
					if (!matchedSlash) {
						start = i + 1;
						break;
					}
				} else {
					if (firstNonSlashEnd === -1) {
						// We saw the first non-path separator, remember this index in case
						// we need it if the extension ends up not matching
						matchedSlash = false;
						firstNonSlashEnd = i + 1;
					}
					if (extIdx >= 0) {
						// Try to match the explicit extension
						if (code === ext.charCodeAt(extIdx)) {
							if (--extIdx === -1) {
								// We matched the extension, so mark this as the end of our path
								// component
								end = i;
							}
						} else {
							// Extension does not match, so our result is the entire path
							// component
							extIdx = -1;
							end = firstNonSlashEnd;
						}
					}
				}
			}
			
			if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
			return path.slice(start, end);
		} else {
			for (i = path.length - 1; i >= 0; --i) {
				if (path.charCodeAt(i) === 47 /*/*/) {
					// If we reached a path separator that was not part of a set of path
					// separators at the end of the string, stop now
					if (!matchedSlash) {
						start = i + 1;
						break;
					}
				} else if (end === -1) {
					// We saw the first non-path separator, mark this as the end of our
					// path component
					matchedSlash = false;
					end = i + 1;
				}
			}
			
			if (end === -1) return '';
			return path.slice(start, end);
		}
	},
	
	extname: function extname(path) {
		assertPath(path);
		var startDot = -1;
		var startPart = 0;
		var end = -1;
		var matchedSlash = true;
		// Track the state of characters (if any) we see before our first dot and
		// after any path separator we find
		var preDotState = 0;
		for (var i = path.length - 1; i >= 0; --i) {
			var code = path.charCodeAt(i);
			if (code === 47 /*/*/) {
				// If we reached a path separator that was not part of a set of path
				// separators at the end of the string, stop now
				if (!matchedSlash) {
					startPart = i + 1;
					break;
				}
				continue;
			}
			if (end === -1) {
				// We saw the first non-path separator, mark this as the end of our
				// extension
				matchedSlash = false;
				end = i + 1;
			}
			if (code === 46 /*.*/) {
				// If this is our first dot, mark it as the start of our extension
				if (startDot === -1)
					startDot = i;
				else if (preDotState !== 1)
					preDotState = 1;
			} else if (startDot !== -1) {
				// We saw a non-dot and non-path separator before our dot, so we should
				// have a good chance at having a non-empty extension
				preDotState = -1;
			}
		}
		
		if (startDot === -1 || end === -1 ||
			// We saw a non-dot character immediately before the dot
			preDotState === 0 ||
			// The (right-most) trimmed path component is exactly '..'
			preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
			return '';
		}
		return path.slice(startDot, end);
	},
	
	format: function format(pathObject) {
		if (pathObject === null || typeof pathObject !== 'object') {
			throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
		}
		return _format('/', pathObject);
	},
	
	parse: function parse(path) {
		assertPath(path);
		
		var ret = { root: '', dir: '', base: '', ext: '', name: '' };
		if (path.length === 0) return ret;
		var code = path.charCodeAt(0);
		var isAbsolute = code === 47 /*/*/;
		var start;
		if (isAbsolute) {
			ret.root = '/';
			start = 1;
		} else {
			start = 0;
		}
		var startDot = -1;
		var startPart = 0;
		var end = -1;
		var matchedSlash = true;
		var i = path.length - 1;
		
		// Track the state of characters (if any) we see before our first dot and
		// after any path separator we find
		var preDotState = 0;
		
		// Get non-dir info
		for (; i >= start; --i) {
			code = path.charCodeAt(i);
			if (code === 47 /*/*/) {
				// If we reached a path separator that was not part of a set of path
				// separators at the end of the string, stop now
				if (!matchedSlash) {
					startPart = i + 1;
					break;
				}
				continue;
			}
			if (end === -1) {
				// We saw the first non-path separator, mark this as the end of our
				// extension
				matchedSlash = false;
				end = i + 1;
			}
			if (code === 46 /*.*/) {
				// If this is our first dot, mark it as the start of our extension
				if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
			} else if (startDot !== -1) {
				// We saw a non-dot and non-path separator before our dot, so we should
				// have a good chance at having a non-empty extension
				preDotState = -1;
			}
		}
		
		if (startDot === -1 || end === -1 ||
			// We saw a non-dot character immediately before the dot
			preDotState === 0 ||
			// The (right-most) trimmed path component is exactly '..'
			preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
			if (end !== -1) {
				if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
			}
		} else {
			if (startPart === 0 && isAbsolute) {
				ret.name = path.slice(1, startDot);
				ret.base = path.slice(1, end);
			} else {
				ret.name = path.slice(startPart, startDot);
				ret.base = path.slice(startPart, end);
			}
			ret.ext = path.slice(startDot, end);
		}
		
		if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';
		
		return ret;
	},
	
	sep: '/',
	delimiter: ':',
	win32: null,
	posix: null
};

posix.posix = posix;

module$2.exports = posix;

//>>>>>>Node2Coke>>>>>>
var path = module$1$1.exports;
//<<<<<<Node2Coke<<<<<<

var JAXDisk,jaxDisk;
var JAXMemDisk,jaxMemDisk;
var JAXRouteResponse;
var heartBeating=false;
let listenCnt=0;
function _heartBeat(){
	fetch("/heart-beat").then(res=>{
		if(!res.ok){
			console.log("SW-heat-beat failed");
		}
	});
	if(heartBeating)
		setTimeout(_heartBeat,5000);
}
function startHeartBeat(){
	if(heartBeating)
		return;
	heartBeating=true;
	_heartBeat();
}

function startListenSW(){
	if(!listenCnt){
		listenCnt=1;
		navigator.serviceWorker.onmessage=JAXDisk.handleSWMessage.bind(JAXDisk);
		startHeartBeat();
	}else {
		listenCnt++;
	}
}

function stopListenSW(){
	if(listenCnt>0) {
		listenCnt--;
		if(!listenCnt){
			navigator.serviceWorker.onmessage=null;
		}
	}
}

//***************************************************************************
//JAX's virtual disk system for web
//***************************************************************************
JAXDisk=function(diskName,majorDisk=null,code="")
{
	this.name=diskName;
	//this.dbStore=new Store('JAXDisk_'+diskName, code?(code+"@"+diskName):diskName);
	this.dbStore=new JAXDiskStore(diskName);
	this.writeObj=null;
	this.writeVsn=0;
	if(majorDisk){
		majorDisk.subDisk[code]=this;
	}else {
		JAXDisk.diskHash[diskName] = this;
		this.subDisk={};
	}
	this.refCount=1;
	this.infoStore=new JAXDiskStore(diskName, "info");
	this.baseStore=new JAXDiskStore(diskName, "base");
	this.inMemory=false;
	this.memDisk=null;
	this.syncAcessPms=null;
};

//---------------------------------------------------------------------------
//All available disk:
//JAXDisk.sysStore=new Store('JAXDisk_', "System");
JAXDisk.sysStore=JAXDiskStore.systemStore();
JAXDisk.disks=null;
JAXDisk.diskHash={};

//***************************************************************************
//JAXDisk static-system functions:
//***************************************************************************
{
	//---------------------------------------------------------------------------
	//Init jax-disk system.
	JAXDisk.init=async function(refresh=false) {
		if(JAXDisk.disks && !refresh){
			return;
		}
		return get$1("disks", JAXDisk.sysStore).then(list => {
			if (Array.isArray(list)) {
				//list.push("RouteTest");
				JAXDisk.disks = new Set(list);
			} else {
				JAXDisk.disks = new Set();
				set$1("disks", [], JAXDisk.sysStore).then(() => {
				});
			}
		});
	};
	
	//---------------------------------------------------------------------------
	//Open an disk, may create new disk if param create is true:
	JAXDisk.openDisk = async function (diskName, create) {
		let disk;
		if(!this.disks) {
			await this.init();
		}
		disk = this.diskHash[diskName];
		if (disk) {
			//Check if the disk is still there:
			try {
				let list = await get$1("disks", JAXDisk.sysStore);
				if (list.indexOf(diskName) >= 0) {
					disk.refCount++;
					return disk;
				} else {
					//The disk is removed.
					this.disks.delete(diskName);
					delete this.diskHash[diskName];
					return null;
				}
			}catch(err) {
				return null;
			}
		}
		if (!this.disks.has(diskName)) {
			let list=await get$1("disks",JAXDisk.sysStore);
			if(list && list.indexOf(diskName)>=0){
				this.disks.add(diskName);
				return new JAXDisk(diskName);
			}
			if (create) {
				return await JAXDisk.newDisk(diskName);
			}
			return null;
		}//else:
		/*if(diskName==="RouteTest"){
			return new JAXDisk(diskName);
		}*/
		let list=await get$1("disks",JAXDisk.sysStore);
		if(list && list.indexOf(diskName)>=0) {
			return new JAXDisk(diskName);
		}
		//The disk is removed.
		this.disks.delete(diskName);
		delete this.diskHash[diskName];
		return null;
	};
	
	//---------------------------------------------------------------------------
	//Check if a disk is exist:
	JAXDisk.diskExist = function (diskName,doubleCheck=0) {
		var self=this;
		return new Promise((resolve, reject) => {
			if (self.disks.has(diskName)) {
				resolve(1);
			} else {
				if(doubleCheck){
					//再次检查数据库:
					return get$1("disks",JAXDisk.sysStore).then(list=>{
						if(list.indexOf(diskName)>=0){
							JAXDisk.disks.add(diskName);
							resolve(1);
						}else {
							resolve(0);
						}
					});
				}else {
					resolve(0);
				}
			}
		});
	};
	
	//---------------------------------------------------------------------------
	//Create a new disk:
	JAXDisk.newDisk = function (diskName) {
		let self=this,diskObj;
		if(diskName.indexOf("/")>=0 || diskName.indexOf("*")>=0){
			throw new Error("New disk: illegal name.");
		}
		return new Promise((resolve, reject) => {
			if (self.disks.has(diskName)) {
				self.openDisk(diskName,0).then((disk)=>{
					resolve(disk);
				});
				return;
			}
			self.disks.add(diskName);
			set$1('disks', Array.from(self.disks), self.sysStore).then(() => {
				//let store=new Store('JAXDisk_'+diskName, diskName,1);
				let store=new JAXDiskStore(diskName);
				set$1(".",{},store).then(()=>{
					diskObj=new JAXDisk(diskName);
					resolve(diskObj);
				});
			});
		});
	};
	
	//---------------------------------------------------------------------------
	//Get a disk's info VO:
	JAXDisk.getDiskInfo=async function(diskName){
		let disk,infoStore;
		if(!this.disks) {
			await this.init();
		}
		disk=await this.openDisk(diskName,false);
		if(!disk){
			return null;
		}
		infoStore=disk.infoStore;
		if(!infoStore){
			//disk.infoStore=infoStore=new Store('JAXDiskInfo_'+diskName, diskName,1);
			disk.infoStore=infoStore=new JAXDiskStore(diskName, "info");
		}
		return await get$1("info",infoStore);
	};
	
	//---------------------------------------------------------------------------
	//Set a disk's info VO:
	JAXDisk.setDiskInfo=async function(diskName,info){
		let disk,infoStore,pms;
		if(!this.disks) {
			await this.init();
		}
		disk=await this.openDisk(diskName);
		if(!disk){
			return null;
		}
		infoStore=disk.infoStore;
		if(!infoStore){
			//disk.infoStore=infoStore=new Store('JAXDiskInfo_'+diskName, diskName,1);
			disk.infoStore=infoStore=new JAXDiskStore(diskName, "info");
			await set$1("info",info,infoStore);
			return;
		}
		if(disk.writeObj){
			await disk.writeObj;
		}
		pms=set$1("info",info,infoStore);
		disk.writeObj=pms;
		pms.writeVsn=disk.writeVsn++;
		return pms;
	};
	
	//---------------------------------------------------------------------------
	//Get a disk's info VO:
	JAXDisk.getDiskAttr=async function(diskName,attr){
		let disk,infoStore;
		if(!this.disks) {
			await this.init();
		}
		disk=await this.openDisk(diskName,false);
		if(!disk){
			return null;
		}
		infoStore=disk.infoStore;
		if(!infoStore){
			disk.infoStore=infoStore=new JAXDiskStore(diskName, "info");
		}
		return await get$1("attr_"+attr,infoStore);
	};
	
	//---------------------------------------------------------------------------
	//Set a disk's attr:
	JAXDisk.setDiskAttr=async function(diskName,key,val){
		let disk,infoStore,pms;
		if(!this.disks) {
			await this.init();
		}
		disk=await this.openDisk(diskName);
		if(!disk){
			return null;
		}
		infoStore=disk.infoStore;
		if(!infoStore){
			disk.infoStore=infoStore=new JAXDiskStore(diskName, "info");
			await set$1("attr_"+key,val,infoStore);
			return;
		}
		if(disk.writeObj){
			await disk.writeObj;
		}
		pms=set$1("attr_"+key,val,infoStore);
		disk.writeObj=pms;
		pms.writeVsn=disk.writeVsn++;
		return pms;
	};
	
	//---------------------------------------------------------------------------
	//Remove a disk, clear the DB(but not drop the db)
	JAXDisk.dropDisk = async function (diskName,dropDB=false) {
		let self,diskObj;
		self=this;
		diskObj=await self.openDisk(diskName,false);
		if(diskObj){
			try {
				if (diskObj.dbStore) {
					await clear(diskObj.dbStore);
					if (diskObj.infoStore) {
						await clear(diskObj.infoStore);
					}
					if (diskObj.baseStore) {
						await clear(diskObj.baseStore);
					}
				}
			}catch(err){
				console.log(`Drop disk ${diskName} error: ${err}`);
				return false;
			}
		}else {
			return false;
		}
		self.disks.delete(diskName);
		delete self.diskHash[diskName];
		await set$1('disks', Array.from(self.disks), self.sysStore);
		if(dropDB){
			drop(diskObj.dbStore.dbName);
		}
		return true;
	};
	
	//---------------------------------------------------------------------------
	//Get current disks list:
	JAXDisk.getDisks=function(){
		return Array.from(this.disks);
	};
	
	//---------------------------------------------------------------------------
	//Get current disk names
	JAXDisk.getDiskNames=async function(){
		let list,i,n,name,disk;
		await this.init(true);
		list=Array.from((this.disks));
		n=list.length;
		for(i=0;i<n;i++){
			name=list[i];
			disk=await JAXDisk.openDisk(name,0);
			if(!disk){
				list.splice(i,1);
				JAXDisk.disks.delete(name);
				delete JAXDisk.diskHash[name];
				n--;i--;
			}
		}
		return list;
	};
	
	//---------------------------------------------------------------------------
	//Make a disk in-memory so can sync accessed
	JAXDisk.syncDisk=async function(diskName,create=false){
		let disk;
		disk=await JAXDisk.openDisk(diskName,create);
		if(!disk)
			return false;
		if(disk.memDisk){
			await disk.syncAcessPms;
			return true;
		}
		return await disk.syncAccess();
	};
	
	//---------------------------------------------------------------------------
	//Get package path's real path:
	JAXDisk.getPkgPath=async function(pkgPath){
		let pkgName,path$1,pos,pkgJSON,pkgRoot;
		if(!pkgPath.startsWith("/@")){
			throw new Error(`${pkgPath} is not a packages path (starts with "/@").`);
		}
		pos=pkgPath.indexOf("/",2);
		if(pos>0){
			pkgName=pkgPath.substring(2,pos);
			path$1=pkgPath.substring(pos+1);
		}else {
			pkgName=pkgPath.substring(2);
			path$1="";
		}
		try {
			pkgJSON = await JAXDisk.readFile(`/coke/lib/${pkgName}.json`, "utf8");
			pkgJSON=JSON.parse(pkgJSON);
			pkgRoot=pkgJSON.path;
			if(!path$1){
				return pkgRoot;
			}
			return path.join(pkgRoot,path$1);
		}catch(err){
			throw new Error(`${pkgName} is not a installed pkg`);
		}
	};
	
	//-----------------------------------------------------------------------
	//Get package's main entry absolute-path:
	JAXDisk.getPkgMain=async function(pkgName){
		try {
			let pkgJSON;
			pkgJSON = await JAXDisk.readFile(`/coke/lib/${pkgName}.json`, "utf8");
			pkgJSON=JSON.parse(pkgJSON);
			return pkgJSON.main;
		}catch(err){
			throw new Error(`${pkgName} is not a installed pkg`);
		}
	};
}

async function digestBytes(buf) {
	let hex;
	const hashBuffer = await crypto.subtle.digest('SHA-256', buf);       	    	// hash the message
	const hashArray = Array.from(new Uint8Array(hashBuffer));                     			// convert buffer to byte array
	hex= hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
	return hex;
}

function divPath(dirPath)
{
	let pos,dirName,upPath;
	//Split dir upper and base:
	if(dirPath.endsWith("/")){
		dirPath=dirPath.substring(0,dirPath.length-1);
	}
	pos=dirPath.lastIndexOf("/");
	if(pos>=0){
		dirName=dirPath.substring(pos+1);
		upPath=dirPath.substring(0,pos);
	}else {
		dirName=dirPath;
		upPath="";
	}
	if(upPath.startsWith("/")){
		upPath=upPath.substring(1);
	}
	return [dirName,upPath];
}

async function readStream(stream){
	let chunks=[];
	let done,value,vo,block;
	let reader,totalSize,data,offset;
	reader=stream.getReader();
	totalSize=0;
	do {
		vo = await reader.read();
		done=vo.done;
		value=vo.value;
		if(value){
			chunks.push(value);
			totalSize+=value.length;
		}
	}while(!done);
	data=new Uint8Array(totalSize);
	offset=0;
	for(let i=0,n=chunks.length;i<n;i++){
		block=chunks[i];
		data.set(block,offset);
		offset+=block.length;
	}
	return data;
}

JAXDisk.prototype=jaxDisk={};
let notifyModifyAct;//Function to notify file system changes to Service work

//***************************************************************************
//Watch and route features
//***************************************************************************
{
	let watching=false;
	let watchList=[];
	let watchClientId=null;
	let watchStubId=0;
	let watchResolveCallback=null;
	let watchResolveStubId=0;
	let routeRegs={};
	
	//-----------------------------------------------------------------------
	JAXDisk.handleSWMessage=function(event){
		let sw=navigator.serviceWorker.controller;
		let data=event.data;
		let msg=data.msg;
		//console.log("Got message from SW: ");
		//console.log(event);
		switch(msg){
			case "WatchOK":
				watchClientId=data.watchId;
				watchResolveCallback && watchResolveCallback(""+watchClientId+"-"+watchResolveStubId);
				break;
			case "WatchAct": {
				let act=data.act;
				let path=data.path;
				let actor=data.actor;
				let stub;
				for(let i=0,n=watchList.length;i<n;i++){
					stub=watchList[i];
					if(path.startsWith(stub.path)) {
						stub.callback(act, path, actor);
					}
				}
				break;
			}
			case "RouteStart":{
				let path=data.path;
				let stub=routeRegs[path];
				stub.routeId=data.routeId;
				if(stub && stub.resolveCallback){
					stub.resolveCallback(stub);
				}
				break;
			}
			case "RouteCall":{
				let path=data.path;
				let stub=routeRegs[path];
				data.callId;
				if(!stub){
					sw.postMessage({msg:"RouteRes",callId:data.callId,res:{code:404,body:"Route not found."}});
				}else {
					let req,request,ret,method,initVO;
					req=data.request;
					method=req.method||"GET";
					initVO={
						method:method,
						referrer:req.referrer,
						headers:req.headers||{}
					};
					if(method==="POST"){
						initVO.body=req.body;
					}
					request=new Request(req.url,initVO);
					try {
						ret = stub.callback(request);
						if(ret instanceof Promise){
							ret.then(async res=>{
								if(res instanceof Response){
									let body;
									if(res.bodyUsed){
										body=await readStream(res.body);
									}else {
										body=null;
									}
									res={
										body:body,
										code:res.status,
										headers:Object.assign({},res.headers),
									};
									sw.postMessage({ msg: "RouteRes", callId: data.callId, res: res });
								}else {
									sw.postMessage({ msg: "RouteRes", callId: data.callId, res: res });
								}
							}).catch((err)=>{
								sw.postMessage({ msg: "RouteRes", callId: data.callId, res: {code:500,body:""+err} });
							});
						}else {
							sw.postMessage({msg:"RouteRes",callId:data.callId,res:ret});
						}
					}catch(err){
						sw.postMessage({ msg: "RouteRes", callId: data.callId, res: {code:500,body:""+err} });
					}
				}
			}
		}
	};
	
	//-----------------------------------------------------------------------
	notifyModifyAct=function(act,path,actor){
		let sw=navigator.serviceWorker.controller;
		if (sw) {
			actor=actor||watchStubId;
			sw.postMessage({msg:"WatchAct",act:act,path:path,actor:actor});
		}
	};
	
	//-----------------------------------------------------------------------
	//Watch a path for changes:
	JAXDisk.watch=async function(path,callback){
		let stub;
		stub={
			path:path,
			callback:callback,
			id:(++watchStubId)
		};
		watchList.push(stub);
		return new Promise((resolve,reject)=>{
			startListenSW();
			if(!watching){
				watching=true;
				if (navigator.serviceWorker.controller) {
					watchResolveCallback=resolve;
					watchResolveStubId=stub.id;
					navigator.serviceWorker.controller.postMessage({msg:"Watch"});
				}
			}else {
				resolve(""+watchClientId+"-"+stub.id);
			}
		});
	};
	
	//-----------------------------------------------------------------------
	//Unwatch:
	JAXDisk.unwatch=function(path,callback){
		let stub;
		for(let i=0,n=watchList.length;i<n;i++){
			stub=watchList[i];
			if(stub.path===path && stub.callback===callback){
				watchList.splice(i,1);
				i--;n--;
			}
		}
		if(!watchList.length){
			navigator.serviceWorker.controller.postMessage({msg:"Unwatch",watchId:watchClientId});
			stopListenSW();
		}
	};
	
	//-----------------------------------------------------------------------
	//Register a global route:
	JAXDisk.regRoute=async function(path,callback){
		return new Promise((resolve,reject)=>{
			startListenSW();
			if(routeRegs[path]){
				throw Error(`Route path ${path} already taken!`);
			}
			routeRegs[path]={
				path: path,
				callback: callback,
				resolveCallback: resolve,
				routeId: 0
			};
			navigator.serviceWorker.controller.postMessage({msg:"RouteOn",path:path});
		});
	};
	
	//-----------------------------------------------------------------------
	JAXDisk.stopRoute=function(path,callback){
		let stub;
		stub=routeRegs[path];
		if(stub){
			if(callback && callback!==stub.callback){
				return;
			}
			navigator.serviceWorker.controller.postMessage({msg:"RouteOff",path:path});
			delete stub[path];
			stopListenSW();
		}
	};
}

//***************************************************************************
//JAXDisk member functions
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//Upgrade a disk for sync access:
	jaxDisk.syncAccess=async function(){
		let memDisk;
		if(this.memDisk) {
			await this.syncAcessPms;
			return true;
		}
		memDisk=new JAXMemDisk(this);
		this.memDisk=memDisk;
		this.syncAcessPms=memDisk.init();
		await this.syncAcessPms;
		return true;
	};
	
	jaxDisk.newDir=async function(dirPath,allowRoot=0,recursive=true){
		var self=this;
		let writeVsn,actorId;
		if(typeof(allowRoot)==="object"){
			let opts=allowRoot;
			allowRoot=opts.allowRoot||false;
			recursive=opts.recursive||true;
			actorId=opts.actor||null;
		}else {
			actorId=null;
		}
		if(dirPath==='.'){
			if(!allowRoot) {
				throw "Error: '.' is not allowed for folder name.";
			}
		}
		
		if(dirPath.endsWith("/")){
			dirPath=dirPath.substring(0,dirPath.length-1);
		}
		if(dirPath.startsWith("/")){
			dirPath=dirPath.substring(1);
		}
		
		async function mkDirList(list){
			let i,n,stub;
			n=list.length;
			for(i=0;i<n;i++) {
				stub=list[i];
				await set$1(stub.path, stub.obj,self.dbStore);
			}
			return list[0];
		}
		
		async function doNewDir() {
			if(self.writeObj && self.writeObj.writeVsn!==writeVsn){
				await self.writeObj;
			}
			
			return get$1(dirPath, self.dbStore).then(async curDirObj => {
				let upPath, dirName;
				let dirList;
				let time = Date.now();
				
				dirList=[];
				
				//Check if path is already there and if it's dir?
				if (curDirObj instanceof Uint8Array) {
					throw "Can't create dir on file!";
				} else if (typeof (curDirObj) === 'object') {
					return curDirObj;
				}
				
				//Path is empty, create dir:
				dirList.push({path:dirPath,obj:{}});
				[dirName, upPath] = divPath(dirPath);
				if(!upPath){
					upPath=".";
				}
				while(upPath){
					let dirObj;
					dirObj=await get$1(upPath, self.dbStore);
					if(!dirObj){
						if(!recursive){
							return null;
						}
						dirObj={};
						dirObj[dirName]={
							name: dirName, dir: 1, createTime: time, modifyTime: time,
						};
						dirList.push({path:upPath,obj:dirObj});
					}else {
						dirObj[dirName]={
							name: dirName, dir: 1, createTime: time, modifyTime: time,
						};
						dirList.push({path:upPath,obj:dirObj});
						break;
					}
					if(upPath==="."){
						throw "newDir: Bad disk structure!";
					}
					[dirName, upPath] = divPath(upPath);
					if(!upPath){
						upPath=".";
					}
				}
				await mkDirList(dirList);
				//Call cross-tab notify:
				notifyModifyAct("NewDir","/"+self.name+"/"+dirPath,actorId);
				return dirList[0].obj;
			})
		}
		//Sync write operation:
		writeVsn=this.writeVsn++;
		self.writeObj=doNewDir();
		self.writeObj.writeVsn=writeVsn;
		self.writeObj.path=dirPath;
		return self.writeObj;
	};
	
	//-----------------------------------------------------------------------
	//Delete an entry-item, if path is a dir, also delete the whole dir tree under it.
	jaxDisk.del=async function(path,opts=null){
		let self=this;
		let writeVsn,actorId,delPath;
		
		if(opts){
			actorId=opts.actor||null;
		}
		
		//console.log("Disk.del: "+path);
		if(path.endsWith("/")){
			path=path.substring(0,path.length-1);
		}
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(path.startsWith("./")){
			path=path.substring(2);
		}
		delPath=path;
		
		//-------------------------------------------------------------------
		//Delete file/dir item array(list)
		async function doDelList(list){
			let i,n,item,pList;
			n=list.length;
			pList=[];
			for(i=0;i<n;i++){
				item=list[i];
				pList.push(del(item,self.dbStore));//Delete one item
			}
			return Promise.allSettled(pList);
		}
		
		//-------------------------------------------------------------------
		//List an dir's all sub-tree items including sub in sub
		async function doMakeList(tgtPath,tgtList){
			let list,i,n,stub;
			tgtList.push(tgtPath);
			list=await self.getEntries(tgtPath);
			n=list.length;
			for(i=0;i<n;i++){
				stub=list[i];
				if(stub.dir){
					await doMakeList((tgtPath?(tgtPath+"/"+stub.name):stub.name),tgtList);
				}else {
					tgtList.push((tgtPath?(tgtPath+"/"+stub.name):stub.name));
				}
			}
		}
		
		//-------------------------------------------------------------------
		//Erase item's entry in upper dir record:
		async function doDelEntry(tgtPath){
			let tgtName,upPath;
			[tgtName,upPath]=divPath(tgtPath);
			if(!upPath){
				upPath=".";
			}
			return get$1(upPath,self.dbStore).then((upDirObj)=>{
				if(upDirObj){
					delete upDirObj[tgtName];
					return set$1(upPath,upDirObj,self.dbStore);
				}
			});
		}
		
		//-------------------------------------------------------------------
		//Check delete item type, exec the del operation:
		async function checkAndDel(){
			if(self.writeObj && self.writeObj.writeVsn!==writeVsn){
				self.writeObj.path;
				await self.writeObj;
			}
			
			return get$1(path,self.dbStore).then(async (delObj)=> {
				let delList;
				
				//Do the delete:
				delList=[];
				if(delObj instanceof Uint8Array) {
					//File, nothing more.
					delList.push(path);
					return doDelList(delList).then(()=>{
						return doDelEntry(path);
					});
				}else if(delObj){
					//Dir, generate the sub-item list to delete
					await doMakeList(path,delList);
					return doDelList(delList).then(()=>{
						return doDelEntry(path);
					});
				}else {
					return doDelEntry(path);
				}
			}).then(()=>{
				notifyModifyAct("Del","/"+self.name+"/"+delPath,actorId);
			});
		}
		writeVsn=this.writeVsn++;
		self.writeObj=checkAndDel();
		self.writeObj.writeVsn=writeVsn;
		self.writeObj.path=path;
		//console.log("Set wait obj: "+path);
		return self.writeObj;
	};
	
	//-----------------------------------------------------------------------
	//Save a file, fileObj can be string, File-Object, etc.
	jaxDisk.saveFile=function(path,fileObj,opts=null){
		let self,tgtName,upPath,byteAry,time,writeVsn,byteHex;
		let actorId,filepath,recursive=true;
		self=this;
		
		if(opts){
			actorId=opts.actor||null;
			recursive=opts.recursive||true;
		}
		
		//console.log("JAXDisk.saveFile: Disk.saveFile: "+path);
		if(path.endsWith("/")){
			throw "JAXDisk.saveFile: Error: filename can't end with '/'!";
		}
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		filepath=path;
		
		[tgtName,upPath]=divPath(path);
		time=Date.now();
		
		//Save byte content to DB, update entry info, make base backup if needed:
		async function saveByteAry(){
			let dirVO,stub,oldData,oldHash;
			//console.log("saveByteAry: "+path+", writeObj: "+(self.writeObj?self.writeObj.filePath:"null"));
			//wait for current update file:
			if(self.writeObj && self.writeObj.writeVsn!==writeVsn){
				await self.writeObj;
			}
			//get upper dirVO:
			dirVO=await get$1(upPath?upPath:".",self.dbStore);
			if(!dirVO){
				throw "Path is not available: "+upPath;
			}
			stub=dirVO[tgtName];
			if(stub){
				//file exists, update stub, save base if 1st :
				oldHash=stub.hash;
				stub.modifyTime=time;
				if(!stub.modified && (oldHash!==byteHex || stub.size!==byteAry.byteLength)) {
					oldData=await get$1(upPath ? (upPath + "/" + tgtName) : tgtName, self.dbStore);
					//save the base file content:
					if(oldData) {
						set$1(upPath ? (upPath + "/" + tgtName) : tgtName, oldData, self.baseStore);
					}
					stub.modified=true;
				}
				stub.size=byteAry.byteLength;
				stub.hash=byteHex;
				//update stub:
			}else {
				//new file, create stub:
				dirVO[tgtName]={
					name:tgtName,dir:0,createTime:time,modifyTime:time,size:byteAry.byteLength,modified:true,
					hash:byteHex
				};
			}
			await set$1(upPath?(upPath+"/"+tgtName):tgtName,byteAry,self.dbStore);
			await set$1(upPath?upPath:".",dirVO,self.dbStore);
			//Call cross-tab notify:
			notifyModifyAct("File","/"+self.name+"/"+filepath,actorId);
		}
		
		async function arrayBuffer(file){
			if(file.arrayBuffer){
				return file.arrayBuffer();
			}
			return new Promise((onDone,onError)=>{
				let reader=new FileReader();
				reader.onload=function(event) {
					let arrayBuffer = event.target.result;
					onDone(arrayBuffer);
				};
				reader.readAsArrayBuffer(file);
			})
		}
		
		function doCopy(){
			//Ensure saved object is ByteArray
			if (typeof (fileObj) === 'string') {
				let encoder = new TextEncoder();
				byteAry = encoder.encode(fileObj);
				return digestBytes(byteAry).then(hex=>{
					writeVsn = self.writeVsn++;
					byteHex=hex;
					self.writeObj =saveByteAry();
					self.writeObj.filePath = path;
					self.writeObj.writeVsn = writeVsn;
					return self.writeObj;
				});
			} else if (fileObj instanceof File) {
				return arrayBuffer(fileObj).then(async buf => {
					byteAry = new Uint8Array(buf);
					return digestBytes(byteAry).then(hex=>{
						writeVsn = self.writeVsn++;
						byteHex=hex;
						self.writeObj =saveByteAry();
						self.writeObj.filePath = path;
						self.writeObj.writeVsn = writeVsn;
						return self.writeObj;
					});
				});
			} else if (fileObj instanceof Uint8Array) {
				byteAry = fileObj;
				return digestBytes(byteAry).then(hex=>{
					writeVsn = self.writeVsn++;
					byteHex=hex;
					self.writeObj =saveByteAry();
					self.writeObj.filePath = path;
					self.writeObj.writeVsn = writeVsn;
					return self.writeObj;
				});
			}else if(fileObj instanceof ArrayBuffer){
				byteAry = new Uint8Array(fileObj);
				return digestBytes(byteAry).then(hex=>{
					writeVsn = self.writeVsn++;
					byteHex=hex;
					self.writeObj =saveByteAry();
					self.writeObj.filePath = path;
					self.writeObj.writeVsn = writeVsn;
					return self.writeObj;
				});
			}
		}
		
		if(upPath){
			return get$1(upPath,self.dbStore).then(pathObj=>{
				//Ensure the target dir is there:
				if(pathObj) {
					if (pathObj instanceof Uint8Array) {
						//upPath is a file, can't go on:
						throw Error(`${upPath} is a file, can't write new file ${path} under it.`);
					}
					return doCopy();
				}else if(recursive){
					return self.newDir(upPath).then(()=>{
						return doCopy();
					});
				}
			});
		}else {
			return doCopy();
		}
	};
	
	//-----------------------------------------------------------------------
	//Load file data as ByteArray
	jaxDisk.loadFile=function(path)
	{
		var self;
		self=this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		return get$1(path,self.dbStore).then(fileObj=>{
			if(fileObj instanceof Uint8Array){
				return fileObj;
			}
			return null;
		});
	};
	
	//-----------------------------------------------------------------------
	//Load file data as text
	jaxDisk.loadText=function(path)
	{
		var self;
		self=this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		return get$1(path,self.dbStore).then(fileObj=>{
			if(fileObj instanceof Uint8Array){
				let enc = new TextDecoder("utf-8");
				return enc.decode(fileObj);
			}
			return null;
		}).catch(err=>{
			return null;
		});
	};
	
	//-----------------------------------------------------------------------
	//Write file, if encode!==null, read as text:
	jaxDisk.writeFile=function(path,obj,encode=null){
		let opts;
		if(encode && typeof(encode)==="object"){
			opts=encode;
			encode=opts.encode||null;
		}else {
			opts=null;
		}
		if(encode) {
			obj=""+obj;//Lazy convert
		}
		return this.saveFile(path,obj,opts);
	};
	
	//-----------------------------------------------------------------------
	//Read file, if encode!==null, read as text:
	jaxDisk.readFile=function(path,encode=null){
		if(encode) {
			return this.loadText(path);
		}else {
			return this.loadFile(path);
		}
	};
	
	//-----------------------------------------------------------------------
	//List sub-item-vo under path, return null if path is a file:
	jaxDisk.getEntries=function(path)
	{
		var self;
		self=this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(!path){
			path='.';
		}
		return get$1(path,self.dbStore).then(fileObj=>{
			if(fileObj instanceof Uint8Array || !fileObj){
				return null;//这是文件，不是目录, 或者路径不存在
			}
			return Object.values(fileObj);
		});
	};
	
	//-----------------------------------------------------------------------
	//Check if a path is existed:
	jaxDisk.isExist=function(path)
	{
		var self=this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(!path){
			path='.';
		}
		return get$1(path,self.dbStore).then(fileObj=>{
			return !!fileObj;
		});
	};
	
	//-----------------------------------------------------------------------
	//Get item entry(info) by path
	jaxDisk.getEntry=async function(path){
		let self=this;
		let dir,fileName;
		[fileName,dir]=divPath(path);
		if(dir.startsWith("/")){
			dir=dir.substring(1);
		}
		if(dir.endsWith("/")){
			dir=dir.substring(0,dir.length-1);
		}
		if(!dir){
			dir='.';
			if(fileName===""){
				return {name:self.name,dir:1,disk:1};
			}
		}
		let dirObj=await get$1(dir,self.dbStore);
		if(dirObj) {
			let entry=dirObj[fileName];
			if(entry instanceof Object){
				return entry;
			}
			return null;
		}
		return null;
	};
	
	//-----------------------------------------------------------------------
	//Set item entry-info by path
	jaxDisk.setEntryInfo=async function(path,info){
		let self=this;
		let entry,pms;
		delete info.name;
		delete info.dir;
		delete info.disk;
		entry=await this.getEntry(path);
		if(typeof(entry)==="object"){
			let dir,fileName,writeVersion;
			[fileName,dir]=divPath(path);
			if(dir.startsWith("/")){
				dir=dir.substring(1);
			}
			if(!dir){
				dir='.';
			}
			Object.assign(entry,info);
			if(self.writeObj){
				await self.writeObj;
			}
			writeVersion=self.writeVsn++;
			self.writeObj=pms=get$1(dir,self.dbStore).then((dirInfo)=>{
				dirInfo[fileName]=entry;
				return set$1(dir,dirInfo,self.dbStore);
			});
			pms.writeVsn=writeVersion;
			return pms;
		}
	};
	
	//-----------------------------------------------------------------------
	//copy a file or dir, src can from another disk (orgDisk)
	jaxDisk.copyFile=function(path,newPath,overwrite=1,orgDisk=null)
	{
		var self=this;
		var dirList,fileList;
		orgDisk=orgDisk||this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(path.endsWith("/")){
			path=path.substring(0,path.length-1);
		}
		if(!path){
			path='.';
		}
		
		if(newPath.startsWith("/")){
			newPath=newPath.substring(1);
		}
		if(newPath.endsWith("/")){
			newPath=newPath.substring(0,newPath.length-1);
		}
		if(!newPath){
			newPath='.';
		}
		
		dirList=[];
		fileList=[];
		
		async function checkInItem(itemPath,tgtPath) {
			var itemObj,subPath,subTgtPath,curItem;
			itemObj=await get$1(itemPath,orgDisk.dbStore);
			if(itemObj instanceof Uint8Array){
				curItem=await get$1(tgtPath,self.dbStore);//Is target there?
				if(curItem) {
					if(overwrite && curItem instanceof Uint8Array) {//Can't overwrite a dir with file!
						fileList.push({org: itemPath, tgt: tgtPath});
					}
				}else {
					fileList.push({org: itemPath, tgt: tgtPath});
				}
			}else if(typeof(itemObj)==="object"){
				var stub,itemName,name;
				dirList.push({org:itemPath,tgt:tgtPath});
				for(itemName in itemObj){
					name=itemName;
					stub=itemObj[name];
					subPath=itemPath?(itemPath+"/"+stub.name):stub.name;
					subTgtPath=tgtPath?(tgtPath+"/"+stub.name):stub.name;
					await checkInItem(subPath,subTgtPath);
				}
			}
		}
		
		function copyOneFile(stub){
			return orgDisk.loadFile(stub.org).then(fileData=>{
				return self.saveFile(stub.tgt,fileData);
			});
		}
		
		return get$1(path,orgDisk.dbStore).then(async fileObj=>{
			let i,n,pList;
			if(!fileObj){
				throw "Missing copy source: "+path;
			}
			await checkInItem(path,newPath);
			pList=[];
			n=dirList.length;
			for(i=0;i<n;i++){
				pList.push(self.newDir(dirList[i].tgt));
			}
			return Promise.allSettled(pList).then(async ()=>{
				let pList=[],p,stub;
				n=fileList.length;
				for(i=0;i<n;i++){
					stub=fileList[i];
					p=copyOneFile(stub);
					pList.push(p);
				}
				return Promise.allSettled(pList).then(()=>{
					return dirList.map((item)=>{
						return item.tgt;
					}).concat(fileList.map(item=>{
						return item.tgt;
					}));
				});
			});
		});
	};
	
	//-----------------------------------------------------------------------
	//Rename a file/dir
	jaxDisk.rename=function(path,newPath)
	{
		var self=this;
		let orgName,orgPath,tgtName,tgtPath;
		
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(path.endsWith("/")){
			path=path.substring(0,path.length-1);
		}
		if(!path){
			path='.';
		}
		[orgName, orgPath] = divPath(path);
		
		if(newPath.startsWith("/")){
			newPath=newPath.substring(1);
		}
		if(newPath.endsWith("/")){
			newPath=newPath.substring(0,newPath.length-1);
		}
		if(!newPath){
			newPath='.';
		}
		[tgtName, tgtPath] = divPath(newPath);
		
		if(tgtPath!==orgPath){
			throw "Path error."
		}
		if(orgName===tgtName){//Same name:
			return (async function(){return true})();
		}
		
		return self.copyFile(path,newPath).then(()=>{
			return self.del(path);
		});
	};
	
	//-----------------------------------------------------------------------
	//Get all items path-name in a flat list:
	jaxDisk.getAllItemPath=async function(){
		return await keys(this.dbStore);
	};
	
	//-----------------------------------------------------------------------
	//Load a file's base version:
	jaxDisk.loadFileBase=async function(path,encode=null){
		let self,fileObj;
		self=this;
		if(path.startsWith("/")){
			path=path.substring(1);
		}
		if(!self.baseStore){
			return null;
		}
		fileObj=await get$1(path,self.baseStore);
		if(fileObj instanceof Uint8Array){
			if(encode) {
				let enc = new TextDecoder("utf-8");
				return enc.decode(fileObj);
			}else {
				return fileObj;
			}
		}
		return null;
	};
}

//***************************************************************************
//JAXDisk functions based on jaxDisk
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//Get disk and path-on-disk:
	let parseDiskPath=JAXDisk.parseDiskPath=async function (fullPath){
		let pos,diskName,diskPath,disk;
		if(fullPath[0]!=='/'){
			fullPath=path.join(JAXDisk.appPath,fullPath);
			if(fullPath[0]!=='/') {
				throw Error('Full path must starts with "/"');
			}
		}
		pos=fullPath.indexOf("/",1);
		if(pos<0){
			diskName=fullPath.substring(1);
			diskPath="";
		}else {
			diskName=fullPath.substring(1,pos);
			diskPath=fullPath.substring(pos+1);
		}
		disk=await JAXDisk.openDisk(diskName,false);
		return [disk,diskPath,diskName];
	};
	
	//-----------------------------------------------------------------------
	//Get disk and path-on-disk:
	let parseDiskPathSync=JAXDisk.parseDiskPath=function (fullPath){
		let pos,diskName,diskPath,disk;
		if(fullPath[0]!=='/'){
			fullPath=path.join(JAXDisk.appPath,fullPath);
			if(fullPath[0]!=='/') {
				throw Error('Full path must starts with "/"');
			}
		}
		pos=fullPath.indexOf("/",1);
		if(pos<0){
			diskName=fullPath.substring(1);
			diskPath="";
		}else {
			diskName=fullPath.substring(1,pos);
			diskPath=fullPath.substring(pos+1);
		}
		disk=JAXDisk.diskHash[diskName];
		return [disk,diskPath,diskName];
	};
	
	//-----------------------------------------------------------------------
	//Make a new dir:
	JAXDisk.newDir=async function(fullPath,allowDisk=false,recursive=true){
		let [disk,diskPath,diskName]=await parseDiskPath(fullPath);
		if(typeof(allowDisk)==="object"){
			let options=allowDisk;
			allowDisk=options.allowDisk||false;
			recursive=options.recursive||false;
		}
		if(!disk){
			if(!allowDisk) {
				return false;
			}else {
				disk=await JAXDisk.newDisk(diskName);
				if(!diskPath){
					return true;
				}
			}
		}
		await disk.newDir(diskPath,false,recursive);
		return true;
	};
	
	JAXDisk.newDirSync=function(fullPath,recursive=true){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(typeof(recursive)==="object"){
			recursive=recursive.recursive||false;
		}
		if(!disk){
			return false;
		}
		disk.newDirSync(diskPath,recursive);
	};
	
	//-----------------------------------------------------------------------
	//Delete a entry:
	JAXDisk.del=async function(fullPath,allowDisk=false,recursive=true){
		let list;
		let [disk,diskPath,diskName]=await parseDiskPath(fullPath);
		if(typeof(allowDisk)==="object"){
			let options=allowDisk;
			allowDisk=options.allowDisk||false;
			recursive=options.recursive||false;
		}
		if(!disk){
			if(!allowDisk) {
				return false;
			}
		}
		list=await JAXDisk.getEntries(fullPath);
		if(list && list.length>0 && !recursive){
			return false;
		}
		if(!diskPath){
			if(!allowDisk){
				return false;
			}
			await JAXDisk.dropDisk(diskName);
			return true;
		}
		await disk.del(diskPath);
		return true;
	};
	
	JAXDisk.delSync=function(fullPath,recursive=true){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(typeof(recursive)==="object"){
			recursive=recursive.recursive||false;
		}
		if(!disk){
			return false;
		}
		disk.delSync(diskPath,recursive);
	};
	
	//-----------------------------------------------------------------------
	//Read a file with full path:
	JAXDisk.readFile=async function(path,encode){
		let data;
		let [disk,diskPath]=await parseDiskPath(path);
		data=await disk.readFile(diskPath,encode);
		if(data===null){
			throw Error(`${path}: can't read contents.`);
		}
		return data;
	};
	
	JAXDisk.readFileSync=function(fullPath,encode){
		let data;
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		data=disk.readFileSync(diskPath,encode);
		if(data===null){
			throw Error(`${fullPath}: can't read contents.`);
		}
		return data;
	};
	
	//-----------------------------------------------------------------------
	//Write a file with full path:
	JAXDisk.writeFile=async function(path,data,encode){
		let [disk,diskPath]=await parseDiskPath(path);
		return await disk.writeFile(diskPath,data,encode);
	};
	
	JAXDisk.writeFileSync=function(fullPath,data,encode){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		return disk.writeFileSync(diskPath,encode);
	};
	
	//-----------------------------------------------------------------------
	//Get a entry with full path:
	JAXDisk.getEntry=async function(path){
		if(path==="/") {
			return {name:"/",dir:1,root:1};
		}
		let [disk,diskPath]=await parseDiskPath(path);
		return await disk.getEntry(diskPath);
	};
	
	JAXDisk.getEntrySync=function(fullPath){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		return disk.getEntrySync(diskPath);
	};
	
	//-----------------------------------------------------------------------
	//Set a entry info with full path:
	JAXDisk.setEntryInfo=async function(path,infoVO){
		let [disk,diskPath]=await parseDiskPath(path);
		return await disk.setEntryInfo(diskPath,infoVO);
	};
	
	JAXDisk.setEntryInfoSync=function(fullPath,infoVO){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		return disk.setEntryInfoSync(diskPath,infoVO);
	};
	
	//-----------------------------------------------------------------------
	//Get entries under a full path:
	JAXDisk.getEntries=async function(path){
		let [disk,diskPath]=await parseDiskPath(path);
		return await disk.getEntries(diskPath);
	};
	
	JAXDisk.getEntriesSync=function(fullPath){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		return disk.getEntriesSync(diskPath);
	};
	
	//-----------------------------------------------------------------------
	//Get entry names under a full path:
	JAXDisk.getEntryNames=async function(path){
		if(path==="/"){
			return await JAXDisk.getDiskNames();
		}
		let list=await JAXDisk.getEntries(path);
		if(!list){
			return null;
		}
		return list.map(item=>item.name);
	};
	JAXDisk.readDir=JAXDisk.getEntryNames;
	
	JAXDisk.getEntryNamesSync=function(fullPath){
		let list=JAXDisk.getEntriesSync(fullPath);
		if(!list){
			return null;
		}
		return list.map(item=>item.name);
	};
	JAXDisk.readDirSync=JAXDisk.getEntryNamesSync;
	
	//-----------------------------------------------------------------------
	//Check if a entry is there
	JAXDisk.isExist=async function(path){
		let entry=await JAXDisk.getEntry(path);
		return !!entry;
	};
	
	JAXDisk.isExistSync=function(fullPath){
		let [disk,diskPath,diskName]=parseDiskPathSync(fullPath);
		if(!disk){
			return false;
		}
		return disk.isExistSync(diskPath);
	};
	
	//-----------------------------------------------------------------------
	//Copy a file or a dir to a new path:
	JAXDisk.copy=async function(orgPath,tgtPath,options){
		let [orgDisk,orgDiskPath]=await parseDiskPath(orgPath);
		let [tgtDisk,tgtDiskPath]=await parseDiskPath(tgtPath);
		let overwrite=options?(options.force||false):false;
		await tgtDisk.copyFile(orgDiskPath,tgtDiskPath,overwrite,orgDisk);
	};
	
	JAXDisk.copySync=function(orgPath,tgtPath,options){
		let [orgDisk,orgDiskPath]=parseDiskPathSync(orgPath);
		let [tgtDisk,tgtDiskPath]=parseDiskPathSync(tgtPath);
		let overwrite=options?(options.force||false):false;
		tgtDisk.copySync(orgDiskPath,tgtDiskPath,overwrite,orgDisk);
	};
}

//***************************************************************************
//JAXMemDisk
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//Constructor:
	JAXMemDisk=function(disk){
		this.disk=disk;
		this.entries=new Map();
		this.name=disk.name;
		this.inMemory=true;
		disk.memDisk=this;
		this.actorId=null;
	};
	jaxMemDisk=JAXMemDisk.prototype={};
	
	//-----------------------------------------------------------------------
	//Init memery disk, read all entries into memory
	jaxMemDisk.init=async function(){
		let disk,keys,plist,entries;
		console.warn(`Sync-init disk: ${this.name}. Better use async access whenever possible.`);
		disk=this.disk;
		entries=this.entries;
		keys=await disk.getAllItemPath();
		plist=[];
		function readEntry(path){
			return get$1(path,disk.store).then(fileObj=>{
				entries.set(path,fileObj);
			});
		}
		for(let key of keys){
			plist.push(readEntry(key));
		}
		await Promise.all(plist);
		"/"+this.name+"/";
		this.actorId=await JAXDisk.watch("/"+this.name,(act,path,actorId)=>{
			if(actorId===this.actorId){
				return;
			}
			switch(act){
				case "NewDir":{
					this.newDirSync(path);
					break;
				}
				case "Del":{
					this.delSync(path);
					break;
				}
				case "File":{
					this.disk.readFile().then(data=>{
						this.writeFileSync(path,data);
					});
					break;
				}
			}
		});
		return true;
	};
	//***********************************************************************
	//Sync functions:
	//***********************************************************************
	{
		//-------------------------------------------------------------------
		//Create a new dir
		jaxMemDisk.newDirSync=function(path){
			let upDir,tgtName,upDirObj,time,curEntry;
			if(path.startsWith("/")){
				path=path.substring(1);
			}
			if(path.endsWith("/")){
				path=path.substring(0,path.length-1);
			}
			if(path==="."||path===""){
				throw Error(`Illegal dir name: ${path}`);
			}
			curEntry=this.entries.get(path);
			if(curEntry){
				if(curEntry.dir){
					return true;
				}
				throw Error(`/${this.name}/path is a file, can't create dir at same place.`);
			}
			[tgtName,upDir]=divPath(path);
			if(!upDir){
				upDir=this.entries.get(".");
			}else {
				upDirObj=this.entries.get(upDir);
			}
			if(!upDirObj){
				this.newDirSync(upDir);
				upDirObj=this.entries.get(upDir);
				if(!upDirObj){
					return false;
				}
			}
			time=Date.now();
			upDirObj[tgtName]={name:tgtName,createTime:time,dir:1};
			this.entries.set(path,{});
			this.disk.newDir(path,{actor:this.actorId});
			return true;
		};
		jaxDisk.newDirSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.newDirSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Delete a entry item:
		jaxMemDisk.delSync=function(path){
			let upDir,tgtName,curEntry,upDirObj;
			if(path.startsWith("/")){
				path=path.substring(1);
			}
			if(path.endsWith("/")){
				path=path.substring(0,path.length-1);
			}
			if(path==="."||path===""){
				throw Error(`Illegal dir name: ${path}`);
			}
			curEntry=this.entries.get(path);
			if(!curEntry){
				return true;
			}
			[tgtName,upDir]=divPath(path);
			if(!upDir){
				upDirObj=this.entries.get(".");
			}else {
				upDirObj=this.entries.get(upDir);
			}
			if(!upDirObj){
				throw Error(`Path: /${this.name}/${upDir} is not available.`);
			}
			if(curEntry.dir){
				let list=this.getEntriesSync(path);
				for(let subItem of list){
					this.delSync(path+"/"+subItem.name);
				}
			}
			delete upDirObj[tgtName];
			this.entries.delete(path);
			this.disk.del(path,{actor:this.actorId});
			return true;
		};
		jaxDisk.delSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.delSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Read a file content
		jaxMemDisk.readFileSync=function(path,encode){
			let data;
			data=this.entries.get(path);
			if(!(data instanceof Uint8Array)){
				return null;
			}
			if(encode){
				let enc = new TextDecoder("utf-8");
				return enc.decode(data);
			}
			return data;
		};
		jaxDisk.readFileSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.readFileSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Write a file
		jaxMemDisk.writeFileSync=function(path,data,encode){
			let byteAry,tgtName,upPath,time,upObj,fileStub,orgStub;
			if(encode) {
				data=""+data;//Lazy convert
			}
			if(path.startsWith("/")){
				path=path.substring(1);
			}
			if(path.endsWith("/")){
				throw Error(`${path} can't be a file name.`)
			}
			
			[tgtName,upPath]=divPath(path);
			time=Date.now();
			
			//Ensure saved object is ByteArray
			if (typeof (data) === 'string') {
				let encoder = new TextEncoder();
				byteAry = encoder.encode(data);
			} else if (data instanceof File) {
				throw Error("File object can't do sync write, convert to Uint8Array before write.");
			} else if (data instanceof Uint8Array) {
				byteAry = data;
			}else if(data instanceof ArrayBuffer){
				byteAry = new Uint8Array(data);
			}
			upObj=this.entries.get(upPath);
			if(upObj) {
				if(!upObj.dir){
					throw Error(`${upPath} is not a dir, can't write file under it.`)
				}
			}else {
				this.newDirSync(upPath);
				upObj=this.entries.get(upPath);
				if(!upObj){
					throw Error(`${upPath} can't be create.`)
				}
			}
			orgStub=upObj[tgtName];
			if(orgStub){
				if(orgStub.dir){
					throw Error(`/${this.name}/${path} is a dir, can't be overwrite by a file.`);
				}
				fileStub=orgStub;
			}else {
				fileStub = {
					name: tgtName,
					modified:true,
					createTime:time
				};
				upObj[tgtName]=fileStub;
			}
			fileStub.size=byteAry.length;
			fileStub.modifyTime=time;
			digestBytes(byteAry).then(hex=>{
				fileStub.hash=hex;
			});
			this.entries.set(path,byteAry);
			this.disk.writeFile(path,byteAry,encode);
		};
		jaxDisk.writeFileSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.writeFileSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Check entry exist:
		jaxMemDisk.isExistSync=function(path){
			if(path.endsWith("/")){
				path=path.substring(0,path.length-1);
			}
			if(path==="" || path==="."){
				return true;
			}
			return !!this.entries.get(path);
			
		};
		jaxDisk.isExistSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.isExistSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Get a file entry:
		jaxMemDisk.getEntrySync=function(path){
			let dir,fileName;
			[fileName,dir]=divPath(path);
			if(dir.startsWith("/")){
				dir=dir.substring(1);
			}
			if(dir.endsWith("/")){
				dir=dir.substring(0,dir.length-1);
			}
			if(!dir){
				dir='.';
				if(fileName===""){
					return {name:this.name,dir:1,disk:1};
				}
			}
			dir=this.entries.get(dir);
			if(dir) {
				let entry=dir[fileName];
				if(entry instanceof Object){
					return entry;
				}
				return null;
			}
			return null;
		};
		jaxDisk.getEntrySync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.getEntrySync(...args);
		};
		
		//-------------------------------------------------------------------
		//Get sub items' entry under a path
		jaxMemDisk.getEntriesSync=function(path){
			let dir;
			if(path.startsWith("/")){
				path=path.substring(1);
			}
			if(path.endsWith("/")){
				path=path.substring(0,path.length-1);
			}
			if(path===""){
				path=".";
			}
			dir=this.entries.get(path);
			if(dir){
				if(dir instanceof Uint8Array){
					return null;//This is a file, not dir
				}
				return Object.values(dir);
			}
			return null;
		};
		jaxDisk.getEntriesSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.getEntriesSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Set a entry info:
		jaxMemDisk.setEntryInfoSync=function(path,info){
			let dir,fileName;
			[fileName,dir]=divPath(path);
			if(dir.startsWith("/")){
				dir=dir.substring(1);
			}
			if(dir.endsWith("/")){
				dir=dir.substring(0,dir.length-1);
			}
			if(!dir){
				return;//Can't set disk root info
			}
			dir=this.entries.get(dir);
			if(dir && dir.dir) {
				let orgInfo=dir[fileName];
				if(!orgInfo){
					return false;
				}
				//These key is critical and not to be changed here:
				delete info.name;
				delete info.dir;
				delete info.disk;
				Object.assign(orgInfo,info);
				return true;
			}
			return false;
		};
		jaxDisk.setEntryInfoSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.setEntryInfoSync(...args);
		};
		
		//-------------------------------------------------------------------
		//Copy a file/dir:
		jaxMemDisk.copySync=function (orgPath,newPath,overwrite=1,orgDisk=null){
			let self=this;
			let orgEntry,tgtEntry;
			if(orgPath.endsWith("/")){
				orgPath=orgPath.substring(0,orgPath.length-1);
			}
			if(newPath.startsWith("/")){
				newPath=newPath.substring(1);
			}
			if(newPath.endsWith("/")){
				newPath=newPath.substring(0,orgPath.length-1);
			}
			if(orgPath.startsWith("/")){
				orgPath=orgPath.substring(1);
			}
			orgDisk=orgDisk||this;
			if(orgDisk.memDisk){
				orgDisk=orgDisk.memDisk;
			}
			if(!orgDisk.readFileSync){
				throw Error(`orgDisk ${orgDisk.name} can not sync access.`);
			}
			function copyOneFile(orgDisk,orgPath,tgtPath){
				let data;
				data=orgDisk.readFileSync(orgPath);
				self.writeFileSync(tgtPath,data);
			}
			orgEntry=orgDisk.getEntrySync(orgPath);
			tgtEntry=self.getEntrySync(newPath);
			if(orgEntry.dir){
				let list,subItem;
				if(tgtEntry && !tgtEntry.dir) {
					if(!overwrite) {
						return false;
					}
					self.delSync(newPath);
				}
				self.newDirSync(newPath);
				list=orgDisk.getEntriesSync(orgPath);
				for(subItem of list){
					if(subItem.dir){
						self.copySync(orgPath+"/"+subItem.name,newPath+"/"+subItem.name,overwrite,orgDisk);
					}else {
						let tgtPath=newPath+"/"+subItem.name;
						tgtEntry=self.getEntrySync(tgtPath);
						if(tgtEntry){
							if(tgtEntry.dir || !overwrite){
								continue;
							}
						}
						copyOneFile(orgDisk,orgPath+"/"+subItem.name,tgtPath);
					}
				}
				return true;
			}else {
				if(tgtEntry){
					if(!overwrite)
						return false;
					if(tgtEntry.dir) {
						throw Error(`/${self.name}/${newPath} is a dir, can't overwrite by file /${orgDisk.name}/${orgPath}`);
					}
				}
				
				copyOneFile(orgDisk,orgPath,newPath);
				return true;
			}
		};
		jaxDisk.copySync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.memDisk.copySync(...args);
		};
		
		//-------------------------------------------------------------------
		//Move a file/dir:
		jaxMemDisk.moveSync=function (orgPath,newPath,overwrite=1,orgDisk=null){
			this.copySync(orgPath,newPath,overwrite,orgDisk);
			orgDisk.delSync(orgPath);
		};
		jaxDisk.moveSync=function(...args){
			if(!this.memDisk){
				throw Error(`Disk ${this.name} is not in memory to async access.`);
			}
			return this.moveSync.copySync(...args);
		};
	}
}

//***************************************************************************
//Route
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//Route request response helper:
	JAXRouteResponse=function(body,init){
		this.body=body;
		if(init){
			this.code=init.status||init.code||200;
			this.headers=init.headers;
		}else {
			this.code=200;
		}
	};
	JAXRouteResponse.prototype={};
	
	//-----------------------------------------------------------------------
	//Construct a json response
	JAXRouteResponse.json=function(obj,pretty=false){
		let json=JSON.stringify(obj,null,pretty?"\t":"");
		return new JAXRouteResponse(json,{
			status:200,
			headers:{
				"Content-Type":"application/json",
				"cache-control":"no-store"
			},
			
		});
	};
	
	//-----------------------------------------------------------------------
	//Construct a text response
	JAXRouteResponse.text=function(text){
		return new JAXRouteResponse(text,{
			status:200,
			headers:{
				"Content-Type":"text/plain",
				"cache-control":"no-store"
			},
			
		});
	};
	
	//-----------------------------------------------------------------------
	//Construct a file respnse
	JAXRouteResponse.file=async function(path$1){
		let data;
		try {
			data = await JAXDisk.readFile(path$1);
		}catch(err){
			data=null;
		}
		if(data){
			let ext=path.extname(path$1);
			let contentType,cache;
			switch(ext){
				default:
					contentType = 'application/octet-stream';
					cache="no-store";
					break;
				case 'txt':
				case 'text':
					contentType = "text/plain";
					cache="no-store";
					break;
				case 'css':
					contentType = "text/css";
					cache="no-store";
					break;
				case 'json':
					contentType = "application/json";
					cache="no-store";
					break;
				case 'js':
				case 'mjs':
					contentType = "text/javascript";
					cache="no-store";
					break;
				case 'png':
					contentType = 'image/png';
					cache="max-age=90, public";
					break;
				case 'jpg':
					contentType = 'image/jpeg';
					cache="max-age=90, public";
					break;
				case 'jpeg':
					contentType = 'image/jpeg';
					cache="max-age=90, public";
					break;
				case 'svg':
					contentType = 'image/svg+xml';
					cache="max-age=90, public";
					break;
				case 'html':
				case 'htm':
					contentType = 'text/html';
					cache="no-store";
					break;
			}
			return new JAXRouteResponse(data,{
				status:200,
				headers:{
					"Content-Type":contentType,
					"cache-control":cache
				},
				
			});
		}
		return new JAXRouteResponse(`File: ${path$1} not found.`,{status:404});
		
	};
}

var JAXAniHtml,__Proto$e;
const STATE_READY$3=1;
const STATE_ANI$3=2;
const STATE_PAUSED$3=3;
const STATE_END$3=4;
const STATE_CANCELED$3=5;

//---------------------------------------------------------------------------
//基于Html的animation:
JAXAniHtml=function(env,def=null,hud=null)
{
	if(!env)
		return;
	JAXAni.call(this,env,def,hud);
	this.aniObj=null;//Html Animation对象
};

__Proto$e=JAXAniHtml.prototype=new JAXAni();

//***************************************************************************
//通用接口:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化:
	__Proto$e.initByDef = function (def) {
		if (this.def) {
			this.jaxEnv.logError("Ani already inited.");
			return;
		}
		this.def = def;
		this.OnFinish=def.OnFinish;
		this.OnCancel=def.OnCancel;
		if (this.hud) {
			this.state = STATE_READY$3;
		}
	};

	//-----------------------------------------------------------------------
	//与Hud绑定:
	__Proto$e.bind2Hud = function (hud) {
		this.hud = hud;
		if (this.def) {
			this.state = STATE_READY$3;
		}
	};

	//-----------------------------------------------------------------------
	//开始动画
	__Proto$e.start = function () {
		let div,def,self;
		if (this.state !== STATE_READY$3) {
			this.jaxEnv.logError("Ani not ready!");
			return;
		}
		self=this;
		def=this.def;
		div=this.hud.webObj;
		this.startTime = Date.now();
		this.state = STATE_ANI$3;
		this.aniObj=div.animate(def.keyframes,def.options||def.duration);
		//设置回调:
		this.aniObj.onfinish=function(){
			self.OnFinish&&self.OnFinish();
		};
		this.aniObj.oncancel=function(){
			self.OnCancel&&self.OnCancel();
		};
	};

	//-----------------------------------------------------------------------
	//暂停动画:
	__Proto$e.pause = function () {
		if(this.state!==STATE_ANI$3){
			this.jaxEnv.logError("Ani not playing!");
			return;
		}
		this.aniObj.pause();
		this.state=STATE_PAUSED$3;
	};

	//-----------------------------------------------------------------------
	//恢复动画:
	__Proto$e.resume = function () {
		if(this.state!==STATE_PAUSED$3){
			this.jaxEnv.logError("Ani not paused!");
			return;
		}
		this.aniObj.play();
		this.state=STATE_ANI$3;
	};

	//-----------------------------------------------------------------------
	//结束动画:
	__Proto$e.finish = function () {
		if(this.state!==STATE_PAUSED$3 && this.state!==STATE_ANI$3){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.aniObj.finish();
		this.aniObj=null;
		this.state=STATE_END$3;
	};

	//-----------------------------------------------------------------------
	//取消动画:
	__Proto$e.cancel = function () {
		if(this.state!==STATE_PAUSED$3 && this.state!==STATE_ANI$3){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.aniObj.cancel();
		this.aniObj=null;
		this.state=STATE_CANCELED$3;
	};
}

//***************************************************************************
//注册类型:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//
	JAXAni.regHudByType("html",function(env,def,hud){
		return new JAXAniHtml(env,def,hud)
	});
}

const STATE_READY$2=1;
const STATE_ANI$2=2;
const STATE_PAUSED$2=3;
const STATE_END$2=4;
const STATE_CANCELED$2=5;

var JAXAniFade,__Proto$d;

//---------------------------------------------------------------------------
//淡入/淡出动画:
JAXAniFade=function(env,def,hud)
{
	if(!env){
		return;
	}
	JAXAni.call(this,env,def,hud);
	this.htmlAni=null;
	this.htmlDef=null;
};

__Proto$d=JAXAniFade.prototype=new JAXAni();

//***************************************************************************
//通用接口:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化:
	__Proto$d.initByDef = function (def) {
		if (this.def) {
			this.jaxEnv.logError("Ani already inited.");
			return;
		}
		this.def = def;
		this.OnFinish=def.OnFinish;
		this.OnCancel=def.OnCancel;
		if (this.hud) {
			this.state = STATE_READY$2;
		}
	};

	//-----------------------------------------------------------------------
	//与Hud绑定:
	__Proto$d.bind2Hud = function (hud) {
		this.hud = hud;
		if (this.def) {
			this.state = STATE_READY$2;
		}
		this.orgDisplay=hud.display;
	};

	//-----------------------------------------------------------------------
	//设置/开始渐入
	__Proto$d.startFadeIn=function(def,time=0){
		var self,htmlDef,hud,vo1,vo2,x,y;
		hud=this.hud;
		self=this;
		vo1={};vo2={};
		def=def||this.def;
		htmlDef={
			keyframes:[vo1,vo2],
			duration:def.time||def.duration||time||200
		};
		vo1.opacity=def.alpha?def.alpha:0;
		vo2.opacity=hud.alpha;
		if("offset" in def){
			x=def.offset[0]||def.offset.x||0;
			y=def.offset[1]||def.offset.y||0;
		}else {
			if("dx" in def){
				x=def.dx||0;
			}
			if("dy" in def){
				y=def.dy||0;
			}
		}
		if(x instanceof Function){
			x=x.call(hud);
		}
		if(y instanceof Function){
			y=y.call(hud);
		}
		vo1.transform='translate('+x+'px, '+y+'px) scale('+(def.scale?def.scale:hud.scale)+')';
		vo2.transform='translate(0,0) scale('+hud.scale+')';
		this.htmlDef=htmlDef;
		this.htmlAni=new JAXAniHtml(this.jaxEnv,htmlDef,this.hud);
		this.hud.display=1;
		//this.hud.alpha=vo1.opacity;
		this.htmlAni.start();
		this.htmlAni.OnFinish=function(){
			//this.hud.alpha=1;
			self.OnFinish&&self.OnFinish();
			self.htmlAni=null;
		};
		this.htmlAni.OnCancel=function(){
			self.OnCancel&&self.OnCancel();
			self.htmlAni=null;
		};
		this.state=STATE_ANI$2;
	};

	//-----------------------------------------------------------------------
	//设置/开始渐出:
	__Proto$d.startFadeOut=function(def,time=0){
		var self,htmlDef,hud,vo1,vo2,x,y;
		self=this;
		hud=self.hud;
		/*if(!this.orgDisplay && !hud.alpha){
			jaxEnv.callAfter(()=>{
				self.OnFinish&&self.OnFinish();
				self.htmlAni=null;
			});
			return;
		}*/
		def=def||this.def;
		vo1={};vo2={};
		htmlDef={
			keyframes:[vo1,vo2],
			duration:def.time||def.duration||time||200
		};
		vo1.opacity=hud.alpha;
		vo2.opacity=def.alpha||0;
		if("offset" in def){
			x=def.offset[0]||def.offset.x||0;
			y=def.offset[1]||def.offset.y||0;
		}else {
			if("dx" in def){
				x=def.dx;
			}
			if("dy" in def){
				y=def.dy;
			}
		}
		if(x instanceof Function){
			x=x.call(hud);
		}
		if(y instanceof Function){
			y=y.call(hud);
		}
		vo1.transform='translate(0,0) scale('+hud.scale+')';
		vo2.transform='translate('+x+'px, '+y+'px) scale('+(def.scale?def.scale:hud.scale)+')';
		this.htmlDef=htmlDef;
		this.htmlAni=new JAXAniHtml(this.jaxEnv,htmlDef,this.hud);
		this.hud.display=1;
		this.htmlAni.start();
		this.htmlAni.OnFinish=function(){
			self.hud.display=0;
			//self.hud.alpha=def.alpha||0;
			self.OnFinish&&self.OnFinish();
			self.htmlAni=null;
		};
		this.htmlAni.OnCancel=function(){
			self.OnCancel&&self.OnCancel();
			self.htmlAni=null;
		};
		this.state=STATE_ANI$2;
	};

	//-----------------------------------------------------------------------
	//开始动画
	__Proto$d.start = function () {
		let def;
		if (this.state !== STATE_READY$2) {
			this.jaxEnv.logError("Ani not ready!");
			return;
		}
		def=this.def;
		switch(def.type){
			case "fadeIn":
			case "in":
			case 1:
				this.startFadeIn();
				break;
			case "fadeOUt":
			case "out":
			case 0:
				this.startFadeOut();
				break;
		}
	};

	//-----------------------------------------------------------------------
	//暂停动画:
	__Proto$d.pause = function () {
		if(this.state!==STATE_ANI$2){
			this.jaxEnv.logError("Ani not playing!");
			return;
		}
		this.htmlAni.pause();
		this.state=STATE_PAUSED$2;
	};

	//-----------------------------------------------------------------------
	//恢复动画:
	__Proto$d.resume = function () {
		if(this.state!==STATE_PAUSED$2){
			this.jaxEnv.logError("Ani not paused!");
			return;
		}
		this.htmlAni.resume();
		this.state=STATE_ANI$2;
	};

	//-----------------------------------------------------------------------
	//结束动画:
	__Proto$d.finish = function () {
		if(this.state!==STATE_PAUSED$2 && this.state!==STATE_ANI$2){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.htmlAni.finish();
		this.htmlAni=null;
		this.state=STATE_END$2;
	};

	//-----------------------------------------------------------------------
	//取消动画:
	__Proto$d.cancel = function () {
		if(this.state!==STATE_PAUSED$2 && this.state!==STATE_ANI$2){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.htmlAni.cancel();
		this.htmlAni=null;
		this.state=STATE_CANCELED$2;
	};
}

//***************************************************************************
//注册类型:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//注册动画类型:
	JAXAni.regHudByType("fadeIn",function(env,def,hud){
		return new JAXAniFade(env,def,hud)
	});
	JAXAni.regHudByType("fadeOut",function(env,def,hud){
		return new JAXAniFade(env,def,hud)
	});
	JAXAni.regHudByType("in",function(env,def,hud){
		return new JAXAniFade(env,def,hud)
	});
	JAXAni.regHudByType("out",function(env,def,hud){
		return new JAXAniFade(env,def,hud)
	});
}

const STATE_READY$1=1;
const STATE_ANI$1=2;
const STATE_PAUSED$1=3;
const STATE_END$1=4;
const STATE_CANCELED$1=5;

var JAXAniPose,__Proto$c;

//---------------------------------------------------------------------------
//淡入/淡出动画:
JAXAniPose=function(env,def,hud)
{
	if(!env){
		return;
	}
	JAXAni.call(this,env,def,hud);
	this.htmlAni=null;
	this.htmlDef=null;
};

__Proto$c=JAXAniPose.prototype=new JAXAni();

//***************************************************************************
//通用接口:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化:
	__Proto$c.initByDef = function (def) {
		if (this.def) {
			this.jaxEnv.logError("Ani already inited.");
			return;
		}
		this.def = def;
		this.OnFinish=def.OnFinish;
		this.OnCancel=def.OnCancel;
		if (this.hud) {
			this.state = STATE_READY$1;
		}
	};

	//-----------------------------------------------------------------------
	//与Hud绑定:
	__Proto$c.bind2Hud = function (hud) {
		this.hud = hud;
		if (this.def) {
			this.state = STATE_READY$1;
		}
	};

	//-----------------------------------------------------------------------
	//开始动画
	__Proto$c.start = function (time) {
		var self,htmlDef,hud,vo1,vo2,x,y,def,w,h;
		if (this.state !== STATE_READY$1) {
			this.jaxEnv.logError("Ani not ready!");
			return;
		}
		hud=this.hud;
		self=this;
		vo1={};vo2={};
		def=def||this.def;
		htmlDef={
			keyframes:[vo1,vo2],
			duration:def.duration||def.time||time||200
		};
		if("alpha" in def) {
			vo1.opacity = hud.alpha;
			vo2.opacity = def.alpha;
		}
		if("x" in def) {
			x = def.x;
			if(x instanceof Function){
				x=x.call(hud);
			}
			switch(hud.anchorH){
				case 0:
					vo1.left=hud.x+"px";
					vo2.left=x+"px";
					break;
				case 1:
					vo1.left=(hud.x-hud.w*0.5)+"px";
					vo2.left=(x-hud.w*0.5)+"px";
					break;
				case 2:
					vo1.left=(hud.x-hud.w)+"px";
					vo2.left=(x-hud.w)+"px";
					break;
			}
		}
		if("y" in def) {
			y = def.y || hud.y;
			if (y instanceof Function) {
				y = y.call(hud);
			}
			switch(hud.anchorH){
				case 0:
					vo1.top=hud.y+"px";
					vo2.top=y+"px";
					break;
				case 1:
					vo1.top=(hud.y-hud.h*0.5)+"px";
					vo2.top=(y-hud.h*0.5)+"px";
					break;
				case 2:
					vo1.top=(hud.y-hud.h)+"px";
					vo2.top=(y-hud.h)+"px";
					break;
			}
		}
		if("scale" in def){
			vo1.transform='scale('+hud.scale+')';
			vo2.transform='scale('+(def.scale?def.scale:hud.scale)+')';
		}
		if("w" in def) {
			w = def.w;
			if(w instanceof Function){
				w=x.call(hud);
			}
			vo1.width=hud.w+"px";
			vo2.width=w+"px";
		}
		if("h" in def) {
			h = def.h;
			if(h instanceof Function){
				h=x.call(hud);
			}
			vo1.height=hud.h+"px";
			vo2.height=h+"px";
		}
		htmlDef.time=def.time;
		this.htmlDef=htmlDef;
		this.htmlAni=new JAXAniHtml(this.jaxEnv,htmlDef,this.hud);
		//this.hud.setDisplay(1);
		this.htmlAni.start();
		this.htmlAni.OnFinish=function(){
			if("x" in def){
				hud.x = def.x;
			}
			if("y" in def){
				hud.y = def.y;
			}
			if("w" in def){
				hud.w = def.w;
			}
			if("h" in def){
				hud.h = def.h;
			}
			if("alpha" in def){
				hud.alpha = def.alpha;
			}
			if("scale" in def){
				hud.scale = def.scale;
			}
			self.OnFinish&&self.OnFinish();
			self.htmlAni=null;
		};
		this.htmlAni.OnCancel=function(){
			self.OnCancel&&self.OnCancel();
			self.htmlAni=null;
		};
	};

	//-----------------------------------------------------------------------
	//暂停动画:
	__Proto$c.pause = function () {
		if(this.state!==STATE_ANI$1){
			this.jaxEnv.logError("Ani not playing!");
			return;
		}
		this.htmlAni.pause();
		this.state=STATE_PAUSED$1;
	};

	//-----------------------------------------------------------------------
	//恢复动画:
	__Proto$c.resume = function () {
		if(this.state!==STATE_PAUSED$1){
			this.jaxEnv.logError("Ani not paused!");
			return;
		}
		this.htmlAni.resume();
		this.state=STATE_ANI$1;
	};

	//-----------------------------------------------------------------------
	//结束动画:
	__Proto$c.finish = function () {
		if(this.state!==STATE_PAUSED$1 && this.state!==STATE_ANI$1){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.htmlAni.finish();
		this.htmlAni=null;
		this.state=STATE_END$1;
	};

	//-----------------------------------------------------------------------
	//取消动画:
	__Proto$c.cancel = function () {
		if(this.state!==STATE_PAUSED$1 && this.state!==STATE_ANI$1){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.htmlAni.cancel();
		this.htmlAni=null;
		this.state=STATE_CANCELED$1;
	};
}

//***************************************************************************
//注册类型:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//注册动画类型:
	JAXAni.regHudByType("pose",function(env,def,hud){
		return new JAXAniPose(env,def,hud)
	});
}

const STATE_READY=1;
const STATE_ANI=2;
const STATE_PAUSED=3;
const STATE_END=4;
const STATE_CANCELED=5;

var JAXAniAuto,__Proto$b;

JAXAniAuto=function(env,def,hud){
	if(!env)
		return;
	this.orgDisplay=1;
	this.orgX=0;
	this.orgY=0;
	this.orgW=0;
	this.orgH=0;
	this.orgAlpha=1;
	this.orgScale=1;
	this.orgRotate=0;
	this.aniObj=null;
	JAXAni.call(this,env,def,hud);
};

__Proto$b=JAXAniAuto.prototype=new JAXAni();
//***************************************************************************
//通用接口:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//初始化:
	__Proto$b.initByDef = function (def) {
		if (this.def) {
			this.jaxEnv.logError("Ani already inited.");
			return;
		}
		this.def = def;
		this.OnFinish = def.OnFinish;
		this.OnCancel = def.OnCancel;
		if (this.hud) {
			this.state = STATE_READY;
		}
	};

	//-----------------------------------------------------------------------
	//与Hud绑定:
	__Proto$b.bind2Hud = function (hud) {
		this.hud = hud;
		if (this.def) {
			this.state = STATE_READY;
		}
		this.orgDisplay=hud.display;
		this.orgX=hud.x;
		this.orgY=hud.y;
		this.orgW=hud.w;
		this.orgH=hud.h;
		this.orgAlpha=hud.alpha;
		this.orgScale=hud.scale;
		this.orgRotate=hud.rotate;
	};

	//-----------------------------------------------------------------------
	//开始动画
	__Proto$b.start = function () {
		let def,self,hud,aniObj,aniDef;
		if (this.state !== STATE_READY) {
			this.jaxEnv.logError("Ani not ready!");
			return;
		}
		self=this;
		hud=this.hud;
		def=this.def;
		aniObj=null;
		aniDef={};
		if(hud.display && !this.orgDisplay){
			//使用FadeIn
			aniDef.type="in";
			aniDef.dx=def.dx||0;
			aniDef.dy=def.dy||0;
			aniDef.alpha=def.alpha||0;
			aniDef.scale=def.scale||this.orgScale;
			aniDef.time=def.time||200;
			aniObj=new JAXAniFade(this.jaxEnv,aniDef,hud);

		}else if(!hud.display && this.orgDisplay){
			//使用FadeOut
			aniDef.type="out";
			aniDef.dx=def.dx||0;
			aniDef.dy=def.dy||0;
			aniDef.alpha=def.alpha||0;
			aniDef.scale=def.scale||this.orgScale;
			aniDef.time=def.time||200;
			aniObj=new JAXAniFade(this.jaxEnv,aniDef,hud);
		}else if(hud.display){
			//使用Pose
			aniDef.type="pose";
			aniDef.x=hud.x;
			aniDef.y=hud.y;
			aniDef.w=hud.w;
			aniDef.h=hud.h;
			aniDef.alpha=hud.alpha;
			aniDef.scale=hud.scale;
			aniDef.time=def.time||200;
			aniObj=new JAXAniPose(this.jaxEnv,aniDef,hud);
			//TODO: 是否重置Hud状态:
			hud.x=this.orgX;
			hud.y=this.orgY;
			hud.w=this.orgW;
			hud.h=this.orgH;
			hud.alpha=this.orgAlpha;
			hud.scale=this.orgScale;
			hud.rotate=this.orgRotate;
		}else {
			this.jaxEnv.callAfter(()=>{
				self.OnFinish&&self.OnFinish();
				self.aniObj=null;
			});
			return;
		}
		this.aniObj=aniObj;
		if(aniObj){
			aniObj.start(def.time);
			this.aniObj.OnFinish=function(){
				self.OnFinish&&self.OnFinish();
				self.aniObj=null;
			};
			this.aniObj.OnCancel=function(){
				self.OnCancel&&self.OnCancel();
				self.aniObj=null;
			};
		}
		this.state=STATE_ANI;
	};

	//-----------------------------------------------------------------------
	//暂停动画:
	__Proto$b.pause = function () {
		if(this.state!==STATE_ANI){
			this.jaxEnv.logError("Ani not playing!");
			return;
		}
		this.aniObj.pause();
		this.state=STATE_PAUSED;
	};

	//-----------------------------------------------------------------------
	//恢复动画:
	__Proto$b.resume = function () {
		if(this.state!==STATE_PAUSED){
			this.jaxEnv.logError("Ani not paused!");
			return;
		}
		this.aniObj.resume();
		this.state=STATE_ANI;
	};

	//-----------------------------------------------------------------------
	//结束动画:
	__Proto$b.finish = function () {
		if(this.state!==STATE_PAUSED && this.state!==STATE_ANI){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.aniObj.finish();
		this.aniObj=null;
		this.state=STATE_END;
	};

	//-----------------------------------------------------------------------
	//取消动画:
	__Proto$b.cancel = function () {
		if(this.state!==STATE_PAUSED && this.state!==STATE_ANI){
			this.jaxEnv.logError("Can't stop ani!");
			return;
		}
		this.aniObj.cancel();
		this.aniObj=null;
		this.state=STATE_CANCELED;
	};
}
//***************************************************************************
//注册类型:
//***************************************************************************
{
	//-----------------------------------------------------------------------
	//注册动画类型:
	JAXAni.regHudByType("auto",function(env,def,hud){
		return new JAXAniAuto(env,def,hud)
	});
}

var JAXHudBox,__Proto$a;

__Proto$a=new JAXHudObj();

JAXHudBox=function(jaxEnv)
{
	var colorBox,colorBorder;
	var border,borderStyle,coner,coners;
	var shadowObj,pxShadow;
	var _attrChanged;
	var signUpdate;
	var gradient,curGradient;

	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.jaxClassFunc=JAXHudBox;

	signUpdate=this.signUpdate;

	colorBox=[128,128,128,255];
	colorBorder=[0,0,0,1];
	border=0;
	borderStyle=0;//0:Solid, 1:dashed, 2:dotted, 3:outset...
	coner=0;
	coners=null;
	_attrChanged=0;
	shadowObj={use:0,x:2,y:2,blur:3,spread:0,color:[0,0,0,0.5]};
	gradient=null;
	curGradient=null;

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//填充颜色:
		Object.defineProperty(this, 'color', {
			get: function () {
				return colorBox;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('color');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('color');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'color', hudView);
						valJXVMap.set('color', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					colorBox[0] = v[0];
					colorBox[1] = v[1];
					colorBox[2] = v[2];
					colorBox[3] = v[3];
				} else if (typeof (v) === 'string') {
					[colorBox[0],colorBox[1],colorBox[2],colorBox[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//边框尺寸:
		Object.defineProperty(this, 'border', {
			get: function () {
				return border;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('border');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('border');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'border', hudView);
						valJXVMap.set('border', v);
					}
					v=v.val;
				}
				if (v!==border) {
					border=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//边框样式:
		Object.defineProperty(this, 'borderStyle', {
			get: function () {
				return borderStyle;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('borderStyle');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('borderStyle');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'borderStyle', hudView);
						valJXVMap.set('borderStyle', v);
					}
					v=v.val;
				}
				if (v!==borderStyle) {
					borderStyle=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//边框颜色:
		Object.defineProperty(this, 'borderColor', {
			get: function () {
				return colorBorder;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('borderColor');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('borderColor');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'borderColor', hudView);
						valJXVMap.set('borderColor', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					colorBorder[0] = v[0];
					colorBorder[1] = v[1];
					colorBorder[2] = v[2];
					colorBorder[3] = v[3];
				} else if (typeof (v) === 'string') {
					[colorBorder[0],colorBorder[1],colorBorder[2],colorBorder[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//圆角尺寸:
		Object.defineProperty(this, 'coner', {
			get: function () {
				return coner;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('coner');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('coner');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'coner', hudView);
						valJXVMap.set('coner', v);
					}
					v=v.val;
				}
				if (v!==coner) {
					coner=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//分别指定的圆角尺寸:
		Object.defineProperty(this, 'coners', {
			get: function () {
				return coners;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('coner');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('coner');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'coner', hudView);
						valJXVMap.set('coner', v);
					}
					v=v.val;
				}
				if (v!==coners) {
					coners=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//影子的Proxy定义:
		pxShadow=new Proxy(this.chdHudList_,{
			get:function(obj,pName){
				if(pName in shadowObj){
					return shadowObj[pName];
				}
				return undefined;
			},
			set:function(obj,pName,v){
				if(pName in shadowObj) {
					let oldV;
					oldV=shadowObj[pName];
					if(v!==oldV){
						shadowObj[pName]=v;
						_attrChanged = 1;
						signUpdate();
					}
				}
				return true;
			}
		});

		//影子的属性定义:
		Object.defineProperty(this, 'shadow', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadow');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadow');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadow', hudView);
						valJXVMap.set('shadow', v);
					}
					v=v.val;
				}
				if(typeof(v)==="object"){
					let attr;
					for(attr in v){
						pxShadow[attr]=v[attr];
					}
					if(! ("use" in v)){
						pxShadow.use=1;
					}
				}else {
					v=v?1:0;
					if(shadowObj.use!==v) {
						shadowObj.use = v ? 1 : 0;
						_attrChanged = 1;
						signUpdate();
					}
				}
			}
		});

		//影子X位移:
		Object.defineProperty(this, 'shadowX', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadowX');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadowX');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadowX', hudView);
						valJXVMap.set('shadowX', v);
					}
					v=v.val;
				}
				if(shadowObj.x!==v) {
					shadowObj.x = v;
					_attrChanged = 1;
					signUpdate();
				}
			}
		});

		//影子Y位移:
		Object.defineProperty(this, 'shadowY', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadowY');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadowY');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadowY', hudView);
						valJXVMap.set('shadowY', v);
					}
					v=v.val;
				}
				if(shadowObj.y!==v) {
					shadowObj.y = v;
					_attrChanged = 1;
					signUpdate();
				}
			}
		});

		//影子Blur模糊:
		Object.defineProperty(this, 'shadowBlur', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadowBlur');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadowBlur');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadowBlur', hudView);
						valJXVMap.set('shadowBlur', v);
					}
					v=v.val;
				}
				if(shadowObj.blur!==v) {
					shadowObj.blur = v;
					_attrChanged = 1;
					signUpdate();
				}
			}
		});

		//影子Spread扩散:
		Object.defineProperty(this, 'shadowSpread', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadowSpread');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadowSpread');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadowSpread', hudView);
						valJXVMap.set('shadowSpread', v);
					}
					v=v.val;
				}
				if(shadowObj.spread!==v) {
					shadowObj.spread = v;
					_attrChanged = 1;
					signUpdate();
				}
			}
		});

		//影子颜色:
		Object.defineProperty(this, 'shadowColor', {
			get:function(){
				return pxShadow;
			},
			set:function(v){
				let color=shadowObj.color;
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('shadowColor');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('shadowColor');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'shadowColor', hudView);
						valJXVMap.set('shadowColor', v);
					}
					v=v.val;
				}
				if(Array.isArray(v)) {
					color[0] = v[0];
					color[1] = v[1];
					color[2] = v[2];
					color[3] = v[3];
					_attrChanged = 1;
					signUpdate();
				}else if(typeof(v)==="string"){
					[color[0],color[1],color[2],color[3]]=JAXEnv.parseColor(v);
				}
			}
		});

		//渐变填充:
		Object.defineProperty(this, 'gradient', {
			get: function () {
				return gradient;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('gradient');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('gradient');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'gradient', hudView);
						valJXVMap.set('gradient', v);
					}
					v=v.val;
				}
				if (v!==gradient) {
					gradient=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//控件客户区域宽度
		Object.defineProperty(this, 'clientW', {
			get: function () {
				return this.size[0]-border*2;
			},
			set: function (v) {
				return v;
			},
			enumerable: true,
			configurable:true
		});

		//控件客户区域宽度
		Object.defineProperty(this, 'clientH', {
			get: function () {
				return this.size[1]-border*2;
			},
			set: function (v) {
				return v;
			},
			enumerable: true,
			configurable:true
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		this._syncWebObjAttr=function(){
			let webObj,style;
			webObj=this.webObj;
			if(webObj){
				style=webObj.style;
				//关于渐变的:
				if(curGradient!==gradient){
					if(gradient) {
						style.background = gradient ? gradient : "";
						curGradient = gradient;
					}
				}
				if(!curGradient){
					style.backgroundColor = "rgba(" + colorBox + ")";
				}
				if(coners){
					//style.borderRadius = "" + coner[0]+"px";
					style.borderRadius = `${coners[0]}px ${coners[1]}px ${coners[2]}px ${coners[3]}px`;
				}else {
					style.borderRadius = "" + coner + "px";
				}
				switch(borderStyle){
					case 0:
					default:
						style.borderStyle="solid";
						break;
					case 1:
						style.borderStyle="dashed";
						break;
					case 2:
						style.borderStyle="dotted";
						break;
				}
				style.borderWidth=""+border+"px";
				style.borderColor="RGBA("+colorBorder+")";

				//关于影子的:
				if(shadowObj.use){
					style.boxShadow=""+shadowObj.x+"px "+shadowObj.y+"px "+shadowObj.blur+"px "+shadowObj.spread+"px rgba("+shadowObj.color[0]+", "+shadowObj.color[1]+", "+shadowObj.color[2]+", "+shadowObj.color[3]+")";
				}else {
					style.boxShadow="none";
				}
			}
			_attrChanged=0;
		};
	}
};

JAXHudBox.prototype=__Proto$a;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudBox.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'color','border','borderStyle','borderColor','coner','coners',
		'shadow','shadowX','shadowY','shadowBlur','shadowSpread','shadowColor',
		'gradient'
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('box', function (env) {
		return new JAXHudBox(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$a.preApplyCSS = function (cssObj)
	{
		var div, father;
		let jaxEnv=this.jaxEnv;
		this.removeAllChildren();

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.style.boxSizing="border-box";
			div.jaxObj = this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$a.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$a.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};

}

var JAXHudText,__Proto$9;

const TXT_ALIGN_LEFT=0;
const TXT_ALIGN_CENTER=1;
const TXT_ALIGN_RIGHT=2;
const TXT_ALIGN_TOP=0;
const TXT_ALIGN_BOTTOM=2;


__Proto$9=new JAXHudObj();

JAXHudText=function(jaxEnv)
{
	var color;
	var autoSizeW,autoSizeH,ellipsis,wrap,alignH,alignV,select;
	var fntName,fntSize,fntBold,fntItalic,fntUnderline;
	var text;
	var textW,textH;
	var _attrChanged;
	var hasNewText;
	var htmlText;
	var signUpdate;
	var cursor=null;
	var self=this;

	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.jaxClassFunc=JAXHudText;

	signUpdate=this.signUpdate;

	color=[128,128,128];

	select=0;
	autoSizeW=0;
	autoSizeH=0;
	ellipsis=0;
	wrap=0;
	alignH=TXT_ALIGN_LEFT;
	alignV=TXT_ALIGN_TOP;

	text="Text";
	htmlText=0;

	fntName=null;
	fntSize=16;
	fntBold=0;
	fntItalic=0;
	fntUnderline=0;
	_attrChanged=0;

	this.innerDiv=null;		//有必要的话，对齐用的内部div

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//文本:
		Object.defineProperty(this, 'text', {
			get: function () {
				if(hasNewText){
					this._syncWebObjAttr();
				}
				if(htmlText){
					return this.innerDiv.innerHTML;
				}
				return this.innerDiv.innerText;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('text');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('text');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'text', hudView);
						valJXVMap.set('text', v);
					}
					v=v.val;
				}
				if(v!==text){
					text=v;
					hasNewText=1;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本:
		Object.defineProperty(this, 'htmlText', {
			get: function () {
				return htmlText?1:0;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('htmlText');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('htmlText');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'htmlText', hudView);
						valJXVMap.set('htmlText', v);
					}
					v=v.val;
				}
				if(v!==text){
					htmlText=v?1:0;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//自动尺寸:
		Object.defineProperty(this, 'autoSize', {
			get: function () {
				return autoSizeW&&autoSizeH;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('autoSize');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('autoSize');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'autoSize', hudView);
						valJXVMap.set('autoSize', v);
					}
					v=v.val;
				}
				v=v?1:0;
				autoSizeW=v;
				autoSizeH=v;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//自动尺寸:
		Object.defineProperty(this, 'autoSizeW', {
			get: function () {
				return autoSizeW;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('autoSizeW');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('autoSizeW');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'autoSizeW', hudView);
						valJXVMap.set('autoSizeW', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(v!==autoSizeW) {
					autoSizeW = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//自动尺寸:
		Object.defineProperty(this, 'autoSizeH', {
			get: function () {
				return autoSizeH;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('autoSizeH');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('autoSizeH');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'autoSizeH', hudView);
						valJXVMap.set('autoSizeH', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(v!==autoSizeH) {
					autoSizeH = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本是否可以选中:
		Object.defineProperty(this, 'select', {
			get: function () {
				return select;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('select');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('select');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'select', hudView);
						valJXVMap.set('select', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(select!==v){
					select=v;
					_attrChanged = 1;
					signUpdate();
					if(!cursor){
						if(!select){
							self.cursor="default";
						}else {
							self.cursor="text";
						}
					}
				}
			},
			enumerable: true
		});

		//文本是否可以选中:
		Object.defineProperty(this, 'editable', {
			get: function () {
				return select;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('editable');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('editable');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'editable', hudView);
						valJXVMap.set('select', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(v){
					this.innerDiv.contentEditable=!!v;
				}
			},
			enumerable: true
		});

		//自动换行:
		Object.defineProperty(this, 'wrap', {
			get: function () {
				return wrap;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('wrap');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('wrap');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'wrap', hudView);
						valJXVMap.set('wrap', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(wrap!==v){
					wrap=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//省略号:
		Object.defineProperty(this, 'ellipsis', {
			get: function () {
				return ellipsis;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('ellipsis');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('ellipsis');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'ellipsis', hudView);
						valJXVMap.set('ellipsis', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(ellipsis!==v){
					ellipsis=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//横向对齐:
		Object.defineProperty(this, 'alignH', {
			get: function () {
				return alignH;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('alignH');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('alignH');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'alignH', hudView);
						valJXVMap.set('alignH', v);
					}
					v=v.val;
				}
				v = v===TXT_ALIGN_LEFT?TXT_ALIGN_LEFT:(v===TXT_ALIGN_RIGHT?TXT_ALIGN_RIGHT:TXT_ALIGN_CENTER);
				if(alignH!==v){
					alignH=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//横向对齐:
		Object.defineProperty(this, 'alignV', {
			get: function () {
				return alignV;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('alignV');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('alignV');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'alignV', hudView);
						valJXVMap.set('alignV', v);
					}
					v=v.val;
				}
				v = v===TXT_ALIGN_TOP?TXT_ALIGN_TOP:(v===TXT_ALIGN_BOTTOM?TXT_ALIGN_BOTTOM:TXT_ALIGN_CENTER);
				if(alignV!==v){
					alignV=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//字体名字:
		Object.defineProperty(this, 'font', {
			get: function () {
				return fntName;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('font');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('font');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'font', hudView);
						valJXVMap.set('font', v);
					}
					v=v.val;
				}
				if (v!==fntName) {
					fntName=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//字体颜色:
		Object.defineProperty(this, 'color', {
			get: function () {
				return color;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('color');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('color');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'color', hudView);
						valJXVMap.set('color', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					color[0] = v[0];
					color[1] = v[1];
					color[2] = v[2];
				} else if (typeof (v) === 'string') {
					[color[0],color[1],color[2],color[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//字体尺寸:
		Object.defineProperty(this, 'fontSize', {
			get: function () {
				return fntSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('fontSize');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('fontSize');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'fontSize', hudView);
						valJXVMap.set('fontSize', v);
					}
					v=v.val;
				}
				if (v!==fntSize) {
					fntSize=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本是否加粗:
		Object.defineProperty(this, 'bold', {
			get: function () {
				return fntBold;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('bold');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('bold');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'bold', hudView);
						valJXVMap.set('bold', v);
					}
					v=v.val;
				}
				if (v!==fntBold) {
					fntBold=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本是否倾斜:
		Object.defineProperty(this, 'italic', {
			get: function () {
				return fntItalic;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('italic');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('italic');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'italic', hudView);
						valJXVMap.set('italic', v);
					}
					v=v.val;
				}
				if (v!==fntItalic) {
					fntItalic=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本是否下划线:
		Object.defineProperty(this, 'underline', {
			get: function () {
				return fntUnderline;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('underline');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('underline');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'underline', hudView);
						valJXVMap.set('underline', v);
					}
					v=v.val;
				}
				if (v!==fntUnderline) {
					fntUnderline=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本本身的宽度
		Object.defineProperty(this, 'textW', {
			get: function () {
				if(_attrChanged){
					this._syncWebObjAttr();
				}
				return textW;
			},
			enumerable: true
		});

		//文本本身的高度
		Object.defineProperty(this, 'textH', {
			get: function () {
				if(_attrChanged){
					this._syncWebObjAttr();
				}
				return textH;
			},
			enumerable: true
		});
		
		//控件光标:
		Object.defineProperty(this, 'cursor', {
			get: function () {
				return cursor;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('clip');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('clip');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'clip', hudView);
						valJXVMap.set('clip', v);
					}
					v=v.val;
				}
				if (cursor !== v) {
					cursor=v;
					if(this.webObj) {
						if (cursor) {
							this.innerDiv.style.cursor=v;
							this.webObj.style.cursor=v;
						}else {
							if(select){
								this.innerDiv.style.cursor="auto";
								this.webObj.style.cursor = "auto";
							}else {
								this.webObj.style.cursor = "auto";
							}
						}
					}
				}
			},
			enumerable: true,
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		//设置字体:
		let _setFont=function(){
			var div,style;
			div=self.innerDiv;
			style=self.innerDiv.style;
			style.userSelect=select?"text":"none";
			style.webkitUserSelect=select?"text":"none";
			style.webkitTouchCallout=select?"text":"none";
			if(self.italic) {
				style.fontStyle="italic";
			}else {
				style.fontStyle="normal";
			}
			if(self.bold) {
				style.fontWeight="bold";
			}else {
				style.fontWeight="normal";
			}
			if(fntUnderline){
				style.textDecoration="underline";
			}else {
				style.textDecoration="";
			}
			//fontTxt +=self.fontSize+"px ";
			style.fontSize=self.fontSize+"px";
			if(self.font){
				style.fontFamily=self.font;
			}else {
				style.fontFamily="";
			}
			//div.style.font=fontTxt;
			div.style.color="rgb("+self.color+")";
		};

		//左上角对齐的文本设置:
		let _setText_LeftTop=function(){
			var div,parentElmt,style,offParent;

			div=self.innerDiv;
			style=div.style;
			delete self.webObj.style.display;
			delete self.webObj.style.alignItems;
			style.position="absolute";

			offParent=div.offsetParent;
			if(!offParent) {
				parentElmt = div.parentElement;
				if (parentElmt) {
					parentElmt.removeChild(div);
				}
				self.jaxEnv.textSizeDiv.appendChild(div);
			}

			if(self.wrap){
				style.width=self.w+"px";
				//style.width="100%";
				style.height="";
				style.wordBreak="break-word";
				style.whiteSpace="";
				style.textOverflow="";
				style.alignSelf="";
				style.textAlign="";

			}else {
				delete style.height;
				delete style.alignSelf;
				delete style.textAlign;
				if(ellipsis){
					//style.width="100%";
					style.width=self.w+"px";
					style.whiteSpace="nowrap";
					style.overflow="hidden";
					style.textOverflow="ellipsis";
				}else {
					style.width="";
					style.wordBreak="keep-all";
					style.whiteSpace="nowrap";
					style.textOverflow="";
				}
			}
			if(htmlText) {
				div.innerHTML = text;
			}else {
				div.innerText=text;
			}
			hasNewText=0;
			textW=div.offsetWidth;
			textH=div.offsetHeight;

			if(!offParent) {
				self.jaxEnv.textSizeDiv.removeChild(div);
				if (parentElmt) {
					let next;
					next = parentElmt.firstChild;
					if (next) {
						parentElmt.insertBefore(div, next);
					} else {
						parentElmt.appendChild(div);
					}
				}
			}
			//console.log('textW='+textW+" textH="+textH);
			if(self.autoSizeW) {
				div.style.left = "0px";
				self.w = textW;
			}else {
				switch (alignH) {
					case TXT_ALIGN_LEFT: {
						div.style.left = "0px";
						break;
					}
					case TXT_ALIGN_CENTER: {
						div.style.left = ((self.w - textW) / 2) + "px";
						break;
					}
					case TXT_ALIGN_RIGHT: {
						div.style.left = (self.w - textW) + "px";
						break;
					}
				}
			}
			if(autoSizeH){
				div.style.top="0px";
				self.h=textH;
			}else {

				switch (alignV) {
					case TXT_ALIGN_TOP: {
						div.style.top = "0px";
						break;
					}
					case TXT_ALIGN_CENTER: {
						div.style.top = ((self.h - textH) / 2) + "px";
						break;
					}
					case TXT_ALIGN_BOTTOM: {
						div.style.top = (self.h - textH) + "px";
						break;
					}
				}
			}
		};

		//---------------------------------------------------------------
		//当控件尺寸发生变化，调用这个函数，调整innerDiv位置:
		this._sizeChanged=function(){
			let div,style;
			div=self.innerDiv;
			style=div.style;
			if(self.autoSizeW) {
				div.style.left = "0px";
			}else {
				//处理wrap情况
				if(self.wrap || self.ellipsis) {
					style.width = self.w + "px";
				}
				switch (alignH) {
					case TXT_ALIGN_LEFT: {
						div.style.left = "0px";
						break;
					}
					case TXT_ALIGN_CENTER: {
						div.style.left = ((self.w - textW) / 2) + "px";
						break;
					}
					case TXT_ALIGN_RIGHT: {
						div.style.left = (self.w - textW) + "px";
						break;
					}
				}
			}
			if(autoSizeH){
				div.style.top="0px";
			}else {

				switch (alignV) {
					case TXT_ALIGN_TOP: {
						div.style.top = "0px";
						break;
					}
					case TXT_ALIGN_CENTER: {
						div.style.top = ((self.h - textH) / 2) + "px";
						break;
					}
					case TXT_ALIGN_BOTTOM: {
						div.style.top = (self.h - textH) + "px";
						break;
					}
				}
			}
			self.OnSizeChanged&&self.OnSizeChanged();
		};

		this._syncWebObjAttr=function(){
			let webObj,innerDiv;
			webObj=this.webObj;
			innerDiv=this.innerDiv;
			if(!webObj){
				_attrChanged=0;
				return;
			}
			innerDiv.innerHTML=""+text;

			//设置字体:
			_setFont();

			//设置文本对齐/自动换行等:
			_setText_LeftTop();

			_attrChanged=0;
		};

	}
};

JAXHudText.prototype=__Proto$9;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudText.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'text','htmlText','autoSize','autoSizeW','autoSizeH','wrap','ellipsis','alignH','alignV','select','editable',
		'font','color','fontSize','bold','italic','underline'
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('text', function (env) {
		return new JAXHudText(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$9.preApplyCSS = function (cssObj)
	{
		var div, father;
		let jaxEnv=this.jaxEnv;

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		this.removeAllChildren();
		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;
			{
				let txtDiv;
				txtDiv=this.webTxtObj = document.createElement('div');
				div.appendChild(txtDiv);
				txtDiv.id="TextDiv";
				this.innerDiv=txtDiv;
				txtDiv.style.cursor="default";
			}
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$9.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		if(this.editable){
			let div=this.innerDiv;
			let self;
			self=this;
			div.onfocus=function(){
				if(self.selectOnFocus){
					self.selectAll();
				}
				if(self.OnFocus){
					self.OnFocus();
				}
				console.log("Focus");
			};
			div.onblur=function(){
				if(self.OnBlur){
					self.OnBlur();
				}
				console.log("Blur");
			};
			div.oninput=function(){
				if(self.OnInput){
					self.OnInput();
				}
			};
			div.onkeyup=function(evt){
				if(evt.code==="Enter"){
					if(self.OnUpdate){
						self.OnUpdate();
					}
				}else if(evt.code==="Escape"){
					if(self.OnCancel){
						self.OnCancel();
					}
				}
			};
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$9.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
			if(this.attrChanged){
				this._syncWebObjAttr();
			}
		}
	};

	//---------------------------------------------------------------
	//开始编辑
	__Proto$9.startEdit=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		if(this.poseChanged) {
			this._syncWebObj();
		}
		this.innerDiv.focus();
		if(this.selectOnFocus){
			this.selectAll();
		}
	};

	//---------------------------------------------------------------
	//结束编辑
	__Proto$9.endEdit=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		if(this.poseChanged) {
			this._syncWebObj();
		}
		this.innerDiv.blur();
	};

	//---------------------------------------------------------------
	//选中全部文本
	__Proto$9.selectAll=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		this.innerDiv.setSelectionRange(0,this.innerDiv.value.length);
	};
	
	//---------------------------------------------------------------
	//控件被点击消息:
	__Proto$9.OnMouseClick=function(e)
	{
		if(this.isGenEvent){
			if(e.srcElement===this.innerDiv && this.OnClickFunc_) {
				e.stopPropagation();
				this.OnClickFunc_.call(this, e);
			}else if(this.OnTreeClickFunc_){
				e.stopPropagation();
				this.OnTreeClickFunc_.call(this, e);
			}
		}
	};
}

var JAXResLib;
var pathMap={};
JAXResLib={
	regPath:function(odir,tdir){
		pathMap[odir]=tdir;
	},
	mapPath:function(path){
		let dir, fname, pos;
		pos=path.lastIndexOf("/");
		if(pos>0){
			dir=path.substring(0,pos);
			fname=path.substring(pos+1);
		}else {
			dir="";
			fname=path;
		}
		dir=pathMap[dir];
		if(dir){
			return dir+"/"+fname;
		}
		return path;
	},
	//TODO: Add more, like image budle:
};

var JAXHudImage,__Proto$8;


const IMG_ALIGN_LEFT=0;
const IMG_ALIGN_CENTER=1;
const IMG_ALIGN_RIGHT=2;
const IMG_ALIGN_TOP=0;
const IMG_ALIGN_BOTTOM=2;

__Proto$8=new JAXHudObj();

JAXHudImage=function(jaxEnv)
{
	var imageURL,imagePos,imageScale;
	var imageObj,imageW,imageH,autoSize,imageLoaded,fitSize;
	var repeatX,repeatY,alignH,alignV;
	var img3x3,img3x3Width;
	var _attrChanged;
	var signUpdate;
	var self;

	if(!jaxEnv)
		return;
	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.jaxClassFunc=JAXHudImage;

	self=this;

	signUpdate=this.signUpdate;

	imageLoaded=0;
	_attrChanged=0;

	img3x3=null;
	img3x3Width=null;
	fitSize=0;
	autoSize=0;
	alignH=IMG_ALIGN_CENTER;
	alignV=IMG_ALIGN_CENTER;
	imageURL="";
	imagePos=[0,0];
	imageScale=1;
	repeatX=0;
	repeatY=0;
	imageW=0;
	imageH=0;
	imageObj=new Image();
	imageObj.crossOrigin="anonymous";
	imageObj.onload=function(){
		let webObj,style;
		webObj=self.webObj;
		if(!webObj){
			return;
		}
		style=self.webObj.style;
		imageLoaded=1;
		imageW = imageObj.width;
		imageH = imageObj.height;
		if(img3x3){
			style.backgroundImage="";
			style.borderImageSource="url(" + imageObj.src + ")";
			style.borderImageSlice=img3x3[1]+" "+img3x3[2]+" "+img3x3[3]+" "+img3x3[0]+" fill";
			style.borderImageWidth=img3x3Width[1]+" "+img3x3Width[2]+" "+img3x3Width[3]+" "+img3x3Width[0]+" fill";
			style.borderImageRepeat="stretch";

		}else {
			style.borderImageSource="";
			style.backgroundImage = "url(" + imageObj.src + ")";
			if (autoSize) {
				self.w = imageW;
				self.h = imageH;
			}
			if(!fitSize){
				style.backgroundSize=(imageW*imageScale)+"px "+(imageH*imageScale)+"px";
			}
		}
		if(self.OnImageLoad){
			self.OnImageLoad();
		}
	};
	imageObj.onerror=function(){
		let webObj,style;
		webObj=self.webObj;
		if(!webObj){
			return;
		}
		style=self.webObj.style;
		imageLoaded=1;
		style.backgroundImage="";
		imageW=0;
		imageH=0;
		if(self.OnImageError){
			self.OnImageError();
		}
	};


	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//自动尺寸:
		Object.defineProperty(this, 'autoSize', {
			get: function () {
				return autoSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('autoSize');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('autoSize');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'autoSize', hudView);
						valJXVMap.set('autoSize', v);
					}
					v=v.val;
				}
				if (autoSize!==v) {
					autoSize=v;
				}
				if(autoSize && imageLoaded){
					self.w=imageW;
					self.h=imageH;
				}
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//使用3x3模式的图片切片参数:
		Object.defineProperty(this, 'img3x3', {
			get: function () {
				return img3x3;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('img3x3');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('img3x3');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'img3x3', hudView);
						valJXVMap.set('img3x3', v);
					}
					v=v.val;
				}
				let url;
				if(Array.isArray((v))){
					if(v.length===1){
						v[1]=v[0];
						v[2]=v[0];
						v[3]=v[0];
					}else if(v.length===2){
						v[2]=v[0];
						v[3]=v[1];
					}
				}else {
					v=[v,v,v,v];
				}
				if (img3x3!==v) {
					img3x3=v;
				}
				if(v && !img3x3Width){
					img3x3Width=v;
				}else if(!v){
					img3x3Width=null;
				}

				//重新设置图片
				url=imageURL;
				imageURL="";
				this.image=url;

				signUpdate();
			},
			enumerable: true
		});

		//使用3x3模式的边框宽度::
		Object.defineProperty(this, 'img3x3Width', {
			get: function () {
				return img3x3Width;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('img3x3Width');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('img3x3Width');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'img3x3Width', hudView);
						valJXVMap.set('img3x3Width', v);
					}
					v=v.val;
				}
				let url;
				if (img3x3Width!==v) {
					img3x3Width=v;
				}
				if(v && !img3x3){
					img3x3=v;
				}else if(!v){
					img3x3=null;
				}

				//重新设置图片
				url=imageURL;
				imageURL="";
				this.image=url;

				signUpdate();
			},
			enumerable: true
		});

		//图片自动适配尺寸:
		Object.defineProperty(this, 'fitSize', {
			get: function () {
				return fitSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('fitSize');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('fitSize');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'fitSize', hudView);
						valJXVMap.set('fitSize', v);
					}
					v=v.val;
				}
				if (fitSize!==v) {
					fitSize=v;
				}
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//横向对齐:
		Object.defineProperty(this, 'alignX', {
			get: function () {
				return alignH;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('alignX');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('alignX');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'alignX', hudView);
						valJXVMap.set('alignX', v);
					}
					v=v.val;
				}
				v = v===IMG_ALIGN_LEFT?IMG_ALIGN_LEFT:(v===IMG_ALIGN_RIGHT?IMG_ALIGN_RIGHT:IMG_ALIGN_CENTER);
				if(alignH!==v){
					alignH=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//横向对齐:
		Object.defineProperty(this, 'alignY', {
			get: function () {
				return alignV;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('alignY');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('alignY');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'alignY', hudView);
						valJXVMap.set('alignY', v);
					}
					v=v.val;
				}
				v = v===IMG_ALIGN_TOP?IMG_ALIGN_TOP:(v===IMG_ALIGN_BOTTOM?IMG_ALIGN_BOTTOM:IMG_ALIGN_CENTER);
				if(alignV!==v){
					alignV=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//图片横向重复属性:
		Object.defineProperty(this, 'repeatX', {
			get: function () {
				return autoSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('repeatX');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('repeatX');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'repeatX', hudView);
						valJXVMap.set('repeatX', v);
					}
					v=v.val;
				}
				if (repeatX!==v) {
					repeatX=v;
				}
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//图片纵向重复属性:
		Object.defineProperty(this, 'repeatY', {
			get: function () {
				return autoSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('repeatY');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('repeatY');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'repeatY', hudView);
						valJXVMap.set('repeatY', v);
					}
					v=v.val;
				}
				if (repeatY!==v) {
					repeatY=v;
				}
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//图片:
		Object.defineProperty(this, 'image', {
			get: function () {
				return imageURL;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('image');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('image');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'image', hudView);
						valJXVMap.set('image', v);
					}
					v=v.val;
				}
				v=JAXResLib.mapPath(v);
				if (imageURL!==v) {
					imageURL=v;
				}
				imageLoaded=0;
				imageObj.src=v;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//图片的偏移:
		Object.defineProperty(this, 'imgPos', {
			get: function () {
				return imagePos;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('imgPos');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('imgPos');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'imgPos', hudView);
						valJXVMap.set('imgPos', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					imagePos[0] = v[0];
					imagePos[1] = v[1];
				}
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//图片的放缩参数:
		Object.defineProperty(this, 'imgScale', {
			get: function () {
				return imageScale;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('imgScale');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('imgScale');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'imgScale', hudView);
						valJXVMap.set('imgScale', v);
					}
					v=v.val;
				}
				if(v>0 || v<0) {
					if (v !== imageScale) {
						imageScale = v;
						_attrChanged = 1;
						signUpdate();
					}
				}
			},
			enumerable: true
		});

		//图片的实际宽度
		Object.defineProperty(this, 'imgW', {
			get: function () {
				return imageW;
			},
			enumerable: false
		});

		//图片的实际高度:
		Object.defineProperty(this, 'imgH', {
			get: function () {
				return imageH;
			},
			enumerable: false
		});

	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		this._syncWebObjAttr=function()
		{
			let webObj,posText;
			webObj=this.webObj;
			if(!webObj){
				return;
			}
			webObj.style.backgroundRepeat=(repeatX?"repeat ":"no-repeat ")+(repeatY?"repeat":"no-repeat");
			if(fitSize){
				webObj.style.backgroundSize=(100*imageScale)+"% "+(100*imageScale)+"%";
			}else {
				webObj.style.backgroundSize=(imageW*imageScale)+"px "+(imageH*imageScale)+"px";
			}
			posText=(alignH===IMG_ALIGN_LEFT?"left ":(alignH===IMG_ALIGN_RIGHT?"right ":"center "));
			if(alignH!==IMG_ALIGN_CENTER) {
				posText += "" + imagePos[0] + "px ";
			}
			posText+=(alignV===IMG_ALIGN_TOP?"top ":(alignV===IMG_ALIGN_BOTTOM?"bottom ":"center "));
			if(alignV!==IMG_ALIGN_CENTER) {
				posText += "" + imagePos[1] + "px ";
			}
			webObj.style.backgroundPosition=posText;
			_attrChanged=0;
		};
	}
};

JAXHudImage.prototype=__Proto$8;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudImage.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'autoSize','fitSize','alignH','alignV','repeatX','repeatY','image','imgPos','imgScale',
	]));

	//---------------------------------------------------------------------------
	//注册Hud类
	JAXHudObj.regHudByType('img', function (env) {
		return new JAXHudImage(env);
	});

	//---------------------------------------------------------------------------
	//注册Hud类
	JAXHudObj.regHudByType('image', function (env) {
		return new JAXHudImage(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$8.preApplyCSS = function (cssObj)
	{
		var div, father;
		let jaxEnv=this.jaxEnv;
		this.removeAllChildren();

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$8.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$8.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};

}

var JAXHudBtn,__Proto$7;

const STATE_NA=-1;
const STATE_UP=0;
const STATE_DOWN=1;
const STATE_OVER=2;
const STATE_GRAY=3;

__Proto$7=new JAXHudObj();

JAXHudBtn=function(jaxEnv)
{
	var curBtnState,curBtnHud,drag;
	var signUpdate;

	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	drag=0;

	this.jaxClassFunc=JAXHudBtn;

	signUpdate=this.signUpdate;

	curBtnState=-1;
	curBtnHud=null;
	this.isPenDown=0;
	this.isPenIn=0;

	this.OnMouseMoveBinded=this.OnMouseMove.bind(this);
	this.OnMouseDownBinded=this.OnMouseDown.bind(this);
	this.OnMouseUpBinded=this.OnMouseUp.bind(this);

	this.OnMouseOverBinded=this.OnMouseOver.bind(this);
	this.OnMouseOutBinded=this.OnMouseOut.bind(this);

	this.OnMouseOver2Binded=this.OnMouseOver2.bind(this);
	this.OnMouseOut2Binded=this.OnMouseOut2.bind(this);

	this.OnButtonDown=null;
	this.OnButtonUp=null;

	this.hudBtnUp_=null;
	this.hudBtnDown_=null;
	this.hudBtnGray_=null;
	this.hudBtnOver_=null;
	this.enabled_=1;

	this.isDragging=0;

	Object.defineProperty(this, 'hudBtnUp_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'hudBtnDown_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'hudBtnGray_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'hudBtnOver_', {enumerable:false,writable:true});
	Object.defineProperty(this, 'enabled_', {enumerable:false,writable:true});


	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//设置按键抬起状态:
		Object.defineProperty(this, 'hudBtnUp', {
			get: function () {
				return this.hudBtnUp_;
			},
			set: function (v) {
				var hud;
				if(this.hudBtnUp_){
					hud=this.hudBtnUp_.release();
				}
				if(v) {
					if (v.isJAXHudObj_) {
						//直接设置Hud控件
						this.hudBtnUp_ = v;
						v.hold();
					} else if (v.type) {
						//创建Hud控件:
						hud = JAXHudObj.createHudByType(v.type, this.jaxEnv, null, v, this);
						this.hudBtnUp_ = hud;
					}
				}else {
					this.hudBtnUp_ = null;
				}
				if(curBtnState===STATE_UP){
					this.state=STATE_NA;
					this.state=STATE_UP;
				}
				signUpdate();
			},
			enumerable: true
		});

		//设置按键按下状态:
		Object.defineProperty(this, 'hudBtnDown', {
			get: function () {
				return this.hudBtnDown_;
			},
			set: function (v) {
				var hud;
				if(this.hudBtnDown_){
					this.hudBtnDown_.release();
				}
				if(v) {
					if (v.isJAXHudObj_) {
						//直接设置Hud控件
						hud = this.hudBtnDown_ = v;
						v.hold();
					} else if (v.type) {
						//创建Hud控件:
						hud = JAXHudObj.createHudByType(v.type, this.jaxEnv, null, v, this);
						this.hudBtnDown_ = hud;
					}
				}else {
					this.hudBtnDown_ = null;
				}
				if(curBtnState===STATE_DOWN){
					this.state=STATE_NA;
					this.state=STATE_DOWN;
				}
				signUpdate();
			},
			enumerable: true
		});

		//设置按置灰状态:
		Object.defineProperty(this, 'hudBtnGray', {
			get: function () {
				return this.hudBtnGray_;
			},
			set: function (v) {
				var hud;
				if(this.hudBtnGray_){
					this.hudBtnGray_.release();
				}
				if(v) {
					if (v.isJAXHudObj_) {
						//直接设置Hud控件
						this.hudBtnGray_ = v;
						v.hold();
					} else if (v.type) {
						//创建Hud控件:
						hud = JAXHudObj.createHudByType(v.type, this.jaxEnv, null, v, this);
						this.hudBtnGray_ = hud;
					}
				}else {
					this.hudBtnGray_ = null;
				}
				if(curBtnState===STATE_GRAY){
					this.state=STATE_NA;
					this.state=STATE_GRAY;
				}
				signUpdate();
			},
			enumerable: true
		});

		//设置按键鼠标悬浮状态:
		Object.defineProperty(this, 'hudBtnOver', {
			get: function () {
				return this.hudBtnOver_;
			},
			set: function (v) {
				var hud;
				if(this.hudBtnOver_){
					this.hudBtnOver_.release();
				}
				if(v) {
					if (v.isJAXHudObj_) {
						//直接设置Hud控件
						hud = this.hudBtnOver_ = v;
						v.hold();
					} else {
						//创建Hud控件:
						hud = JAXHudObj.createHudByType(v.type, this.jaxEnv, null, v, this);
						this.hudBtnOver_ = hud;
					}
				}else {
					this.hudBtnOver_ = null;
				}
				/*if(hud){
					this.webObj.addEventListener('mouseover', this.OnMouseOver2Binded, true);
					this.webObj.addEventListener('mouseleave', this.OnMouseOut2Binded, true);
				}else{
					this.webObj.removeEventListener('mouseover', this.OnMouseOver2Binded, true);
					this.webObj.removeEventListener('mouseleave', this.OnMouseOut2Binded, true);
				}*/
				if(curBtnState===STATE_OVER){
					this.state=STATE_NA;
					this.state=STATE_OVER;
				}
				signUpdate();
			},
			enumerable: true
		});

		//按钮是否置灰:
		Object.defineProperty(this,'enable',{
			get:function(){
				return this.enabled_;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('enable');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('enable');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'enable', hudView);
						valJXVMap.set('enable', v);
					}
					v=v.val;
				}
				v=v?1:0;
				if(v===this.enabled_){
					return;
				}
				this.enabled_=v;
				this.isPenDown=0;
				if(v) {
					this.state = STATE_UP;
				}else {
					this.state = STATE_GRAY;
					this.isPenDown = 0;
				}
			},
			enumerable:true
		});

		//按钮的当前状态
		Object.defineProperty(this,'state',{
			get:function(){
				return curBtnState;
			},
			set:function(v){
				var firstWebChd,stateHud,face;
				if(v===curBtnState){
					return;
				}
				switch(v){
					case STATE_UP:
					default:
						curBtnState=STATE_UP;
						stateHud=this.hudBtnUp_;
						face="up";
						break;
					case STATE_DOWN:
						curBtnState=STATE_DOWN;
						stateHud=this.hudBtnDown_;
						face="down";
						break;
					case STATE_OVER:
						curBtnState=STATE_OVER;
						stateHud=this.hudBtnOver_;
						face="over";
						break;
					case STATE_GRAY:
						curBtnState=STATE_GRAY;
						stateHud=this.hudBtnGray_;
						face="gray";
						break;
					case STATE_NA: {
						curBtnState=STATE_NA;
						if(this.webObj) {
							if (curBtnHud && curBtnHud.webObj) {
								this.webObj.removeChild(curBtnHud.webObj);
							}
							curBtnHud=null;
						}
						return;
					}
				}
				if(!stateHud){
					stateHud=this.hudBtnUp_;
				}
				if(this.webObj) {
					if (curBtnHud && curBtnHud.webObj) {
						this.webObj.removeChild(curBtnHud.webObj);
					}
					firstWebChd=this.webObj.firstChild;
					if (stateHud) {
						curBtnHud=stateHud;
						if (stateHud.webObj) {
							if (firstWebChd) {
								this.webObj.insertBefore(stateHud.webObj, firstWebChd);
							} else {
								this.webObj.appendChild(stateHud.webObj);
							}
						}
					}else {
						curBtnHud=null;
					}
				}
				if(face){
					this.showFace(face);
				}
			},
			enumerable:false
		});

		//按钮是否支持拖拽:
		Object.defineProperty(this,'drag',{
			get:function(){
				return drag;
			},
			set:function(v){
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('enable');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('enable');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'enable', hudView);
						valJXVMap.set('enable', v);
					}
					v=v.val;
				}
				v=v===2?2:(v?1:0);
				drag=v;
			},
			enumerable:true
		});

		//控件的鼠标点击消息:
		Object.defineProperty(this, 'OnClick', {
			get: function () {
				return this.OnClickFunc_;
			},
			set: function (v) {
				var self=this;
				if (this.OnClickFunc_ !== v) {
					this.OnClickFunc_ = v;
				}
				if(this.isLabel){
					if (this.webObj) {
						this.webObj.onclick = v?function(e){self.OnMouseClick(e);}:null;
					}
				}
			},
			enumerable: true,
			configurable:true,
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		this._sizeChanged=function(){
			let hud;
			hud=this.hudBtnUp_;
			if(hud && hud.autoLayout){
				hud._doLayout();
			}
			hud=this.hudBtnDown_;
			if(hud && hud.autoLayout){
				hud._doLayout();
			}
			hud=this.hudBtnOver_;
			if(hud && hud.autoLayout){
				hud._doLayout();
			}
			hud=this.hudBtnGray_;
			if(hud && hud.autoLayout){
				hud._doLayout();
			}
			this.OnSizeChanged&&this.OnSizeChanged();
		};

		this._syncWebObjAttr=function(){
			//TODO: Code this:
		};

		//-------------------------------------------------------------------
		//在全部子节点（包含subs）里执行一个函数:
		this.execInTree=function(func){
			var list,i,n,hud;
			hud=this.hudBtnUp_;
			if(hud){
				if(func(hud)){
					return;
				}
			}
			hud=this.hudBtnDown_;
			if(hud){
				if(func(hud)){
					return;
				}
			}
			hud=this.hudBtnOver_;
			if(hud){
				if(func(hud)){
					return;
				}
			}
			hud=this.hudBtnGray_;
			if(hud){
				if(func(hud)){
					return;
				}
			}
			list=this.chdHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				if(func(list[i])){
					return;
				}
			}
		};
	}
};

JAXHudBtn.prototype=__Proto$7;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudBtn.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'hudBtnDown','hudBtnUp','hudBtnGray','hudBtnOver','enable','drag',
		'OnButtonDown','OnButtonUp'
	]));

	//---------------------------------------------------------------------------
	//注册按键类
	JAXHudObj.regHudByType('btn', function (env) {
		return new JAXHudBtn(env);
	});

	//---------------------------------------------------------------------------
	//注册按键类
	JAXHudObj.regHudByType('button', function (env) {
		return new JAXHudBtn(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//***************************************************************
	//创建控件:
	//***************************************************************
	{
		//---------------------------------------------------------------
		//ApplyCSS的开始，创建WebObj:
		__Proto$7.preApplyCSS = function (cssObj) {
			var div, father;
			let jaxEnv=this.jaxEnv;
			this.removeAllChildren();

			let owner,ownerState;
			father = this.father;
			owner = this.owner;

			if (!this.webObj) {
				if(cssObj.labelHtml){
					this.isLabel=1;
					this.labelObjDiv=document.createElement('div');
					this.labelObjDiv.style.position="absolute";
					this.labelObjDiv.style.height="100px";
					this.labelObjDiv.style.top="-200px";
					this.labelObjDiv.style.opacity="0";
					document.body.appendChild(this.labelObjDiv);
					this.labelObjDiv.innerHTML=cssObj.labelHtml;
					this.labelTarget_=this.labelObjDiv.firstChild;
					this.labelTarget_.onchange=cssObj.OnLabelAction||cssObj.OnLableAction;
				}else if(cssObj.labelFor){
					this.isLabel=1;
					this.labelTarget_=document.getElementById(cssObj.labelFor);
				}
				div = this.webObj = document.createElement('div');
				div.style.position = cssObj.position||"absolute";
				div.style.backgroundColor="rgba(0,0,0,0.0)";
				father = this.father;
				if (father && father.webObj) {
					father.webObj.appendChild(div);
				}
				div.jaxObj = this;
			}
			let style=cssObj.style;
			if(style){
				if(typeof(style)==="string") {
					div.style.cssText += style;
				}else {
					Object.assign(div.style,style);
				}
			}
			if(cssObj.faces){
				cssObj.jaxObjHash=1;
			}
			if(cssObj.jaxId){
				this["#self"]=this;
				//添加这个Hud
				jaxEnv.addHashObj("#"+cssObj.jaxId, this);
			}
			//确定StateObj:
			var stateObj=cssObj.hudState;
			if(stateObj){
				ownerState=father?father.stateObj:(owner?owner.stateObj:null);
				if(!stateObj.isJAXHudState) {
					stateObj = jaxHudState(this.jaxEnv, stateObj);
				}
				this.jaxEnv.pushHudState(stateObj);
				this.stateObj=stateObj;
				this.stateObj_=stateObj;
				stateObj.setupState(this,ownerState,this.hudView);
				if(cssObj.jaxId){
					//添加这个State对象
					jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
				}
			}else {
				this.stateObj=this.jaxEnv.getCurHudState();
			}
		};

		//---------------------------------------------------------------
		//ApplyCSS的最后，设置WebObj属性:
		__Proto$7.postApplyCSS = function (cssObj) {
			let list;
			list = this.items2Add_;
			if (this.enable) {
				this.state = STATE_UP;
			} else {
				this.state = STATE_GRAY;
			}
			if (Array.isArray(list)) {
				this._applyItems(list);
			}

			/*if(this.hudPose.scale!==1){
				console.log("Found scale: "+this.hudPose.scale);
			}*/

			//链接webObj的鼠标消息:
			this.webObj.addEventListener('mousedown', this.OnMouseDownBinded);
			this.webObj.addEventListener('mouseover', this.OnMouseOver2Binded, true);
			this.webObj.addEventListener('mouseleave', this.OnMouseOut2Binded, true);
			if(cssObj.face){
				this.showFace(cssObj.face);
			}
			this._syncWebObj();
			this._holdAttr=false;

			let stateObj=this.stateObj_;
			if(stateObj){
				this.jaxEnv.popHudState(stateObj);
			}
			// if(cssObj.jaxObjHash){
			// 	this.jaxEnv.popObjHasher(this);
			// }
		};

		//---------------------------------------------------------------
		//更新控件内容
		__Proto$7.update = function () {
			let webObj;
			webObj = this.webObj;
			if (webObj) {
				//if (this.poseChanged) {
				{
					this._syncWebObj();
				}
				if (this.attrChanged) {
					this._syncWebObjAttr();
				}
			}
		};
	}

	//***************************************************************
	//鼠标消息:
	//***************************************************************
	{
		//-------------------------------------------------------------------
		//鼠标按下
		__Proto$7.OnMouseDown=function(e)
		{
			if(!this.enable){
				return;
			}
			if(!this.isPenDown) {
				e.stopPropagation();
				e.preventDefault();
				//this.webObj.addEventListener('mousemove', this.OnMouseMoveBinded, true);
				if(this.drag===2 && this.OnDragStart && !this.isDragging){
					let self=this;
					self.isDragging=1;
					self.OnDragStart(e);
					self.jaxEnv.startDrag(e,{
						OnDrag:self.OnDrag?self.OnDrag.bind(self):null,
						OnDone:(e,dx,dy)=>{
							self.isDragging=0;
							self.OnDragEnd&&self.OnDragEnd.call(self,e,dx,dy);
						},
					});
					this.OnDrag&&this.OnDrag(e,0,0);
				}else {
					this.isPenDown = 1;
					this.state = STATE_DOWN;
					this.isPenDown = 1;
					this.state = STATE_DOWN;

					this.webObj.addEventListener('mouseup', this.OnMouseUpBinded, true);
					this.webObj.addEventListener('mouseover', this.OnMouseOverBinded, true);
					this.webObj.addEventListener('mouseout', this.OnMouseOutBinded, true);
					this.jaxEnv.addOnMouseUp(this.OnMouseUpBinded);
					this.OnButtonDown && this.OnButtonDown(1, e);
				}
			}
		};

		//-------------------------------------------------------------------
		//鼠标抬起
		__Proto$7.OnMouseUp=function(e,fromBG)
		{
			if(!this.enable){
				return;
			}
			//console.log("Mouse Up: "+fromBG);
			if(this.isPenDown) {
				this.isPenDown = 0;
				this.state = this.isPenIn?STATE_OVER:STATE_UP;
				//this.webObj.removeEventListener('mousemove', this.OnMouseMoveBinded, true);
				this.webObj.removeEventListener('mouseup', this.OnMouseUpBinded, true);
				this.webObj.removeEventListener('mouseover', this.OnMouseOverBinded, true);
				this.webObj.removeEventListener('mouseout', this.OnMouseOutBinded, true);
				this.jaxEnv.removeOnMouseUp(this.OnMouseUpBinded);
				this.OnButtonDown&&this.OnButtonDown(e);
				if(!fromBG && this.OnClickFunc_ && this.enable){
					this.OnButtonUp&&this.OnButtonUp(1,e);
					if(this.OnClickFunc_(e)!==false){
						this.state = STATE_UP;
					}
				}else {
					this.OnButtonUp&&this.OnButtonUp(0,e);
				}
				e.stopPropagation();
				e.preventDefault();
				if(this.labelTarget_){
					var evt;
					evt=new MouseEvent("click", {
						bubbles: true,cancelable: true,view: window
					});
					this.labelTarget_.dispatchEvent(evt);
				}
			}
		};

		//-------------------------------------------------------------------
		//鼠标移动
		__Proto$7.OnMouseMove=function(e)
		{
			if(!this.enable){
				return;
			}
			if(this.isPenDown) ;
		};

		//-------------------------------------------------------------------
		//按下时鼠标移入
		__Proto$7.OnMouseOver=function(e)
		{
			if(!this.enable){
				return;
			}
			//console.log("Mouse Over");
			if(this.isPenDown) {
				this.state=STATE_DOWN;
				this.OnButtonDown&&this.OnButtonDown(0,e);
			}
		};

		//-------------------------------------------------------------------
		//按下时鼠标移出
		__Proto$7.OnMouseOut=function(e)
		{
			if(!this.enable){
				return;
			}
			//console.log("Mouse Out");
			if(this.isPenDown) {
				this.state=STATE_UP;
				this.OnButtonUp&&this.OnButtonUp(0,e);
				if(this.drag===1 && !this.isDragging && this.OnDragStart){
					let self=this;
					self.isDragging=1;
					self.OnDragStart(e);
					self.jaxEnv.startDrag(e,{
						OnDrag:self.OnDrag?self.OnDrag.bind(self):null,
						OnDone:(e,cancel,dx,dy)=>{
							self.isDragging=0;
							self.OnDragEnd&&self.OnDragEnd.call(self,e,cancel,dx,dy);
						},
					});
					this.OnDrag&&this.OnDrag(e,0,0);
				}
			}
		};

		//-------------------------------------------------------------------
		//抬起时鼠标移入
		__Proto$7.OnMouseOver2=function(e)
		{
			if(!this.enable){
				return;
			}
			this.isPenIn=1;
			if(this.isPenDown) ;else {
				this.state=STATE_OVER;
			}
		};

		//-------------------------------------------------------------------
		//抬起时鼠标移出
		__Proto$7.OnMouseOut2=function(e)
		{
			if(!this.enable){
				return;
			}
			this.isPenIn=0;
			if(this.isPenDown) ;else {
				this.state=STATE_UP;
			}
		};
	}

	//-----------------------------------------------------------------------
	//释放资源:
	__Proto$7.freeHud=function(){
		var father,div;

		if(this.labelObjDiv){
			document.body.removeChild(this.labelObjDiv);
			this.labelObjDiv=null;
			this.labelTarget_=null;
		}

		this.removeAllChildren();
		father=this.father;
		div=this.webObj;
		if(div && father && father.webObj){
			father=div.parentNode;
			if(father){
				father.removeChild(div);
			}
			this.webObj=null;
		}
	};

}

var JAXHudEditBox,__Proto$6;

__Proto$6=new JAXHudObj();

JAXHudEditBox=function(jaxEnv)
{
	var self;
	var colorBox,colorBorder;
	var border,borderStyle,coner;
	var text,fntName,fntSize,fntColor;
	var placeHolder="";
	var selectOnFocus=1;
	var spellCheck=1;
	var outline=1;
	var list=null;
	var _attrChanged,_textChanged;
	var signUpdate;

	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.jaxClassFunc=JAXHudEditBox;

	self=this;
	this.webDataList=null;
	this.inputType="text";

	signUpdate=this.signUpdate;

	colorBox=[255,255,255,255];
	colorBorder=[0,0,0,1];
	border=1;
	borderStyle=0;//0:Solid, 1:dashed, 2:dotted, 3:outset...
	coner=0;
	_attrChanged=0;

	fntColor=[0,0,0,1];

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//填充颜色:
		Object.defineProperty(this, 'bgColor', {
			get: function () {
				return colorBox;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('bgColor');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('bgColor');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'bgColor', hudView);
						valJXVMap.set('bgColor', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					colorBox[0] = v[0];
					colorBox[1] = v[1];
					colorBox[2] = v[2];
					colorBox[3] = v[3];
				} else if (typeof (v) === 'string') {
					[colorBox[0],colorBox[1],colorBox[2],colorBox[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//边框尺寸:
		Object.defineProperty(this, 'border', {
			get: function () {
				return border;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('border');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('border');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'border', hudView);
						valJXVMap.set('border', v);
					}
					v=v.val;
				}
				if (v!==border) {
					border=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//边框样式:
		Object.defineProperty(this, 'borderStyle', {
			get: function () {
				return borderStyle;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('borderStyle');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('borderStyle');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'borderStyle', hudView);
						valJXVMap.set('borderStyle', v);
					}
					v=v.val;
				}
				if (v!==borderStyle) {
					borderStyle=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//边框颜色:
		Object.defineProperty(this, 'borderColor', {
			get: function () {
				return colorBorder;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('borderColor');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('borderColor');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'borderColor', hudView);
						valJXVMap.set('borderColor', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					colorBorder[0] = v[0];
					colorBorder[1] = v[1];
					colorBorder[2] = v[2];
					colorBorder[3] = v[3];
				} else if (typeof (v) === 'string') {
					[colorBorder[0],colorBorder[1],colorBorder[2],colorBorder[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//圆角尺寸:
		Object.defineProperty(this, 'coner', {
			get: function () {
				return coner;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('coner');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('coner');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'coner', hudView);
						valJXVMap.set('coner', v);
					}
					v=v.val;
				}
				if (v!==coner) {
					coner=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本:
		Object.defineProperty(this, 'text', {
			get: function () {
				if(_textChanged){
					self.webObj.value=text;
					_textChanged=0;
				}else if(self.webObj){
					text=self.webObj.value;
				}
				return text;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('text');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('text');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'text', hudView);
						valJXVMap.set('text', v);
					}
					v=v.val;
				}
				if(self.webObj){
					text=self.webObj.value;
				}
				if(v!==text){
					text=v;
					_textChanged = 1;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本提示:
		Object.defineProperty(this, 'placeHolder', {
			get: function () {
				return placeHolder;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('placeHolder');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('placeHolder');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'placeHolder', hudView);
						valJXVMap.set('placeHolder', v);
					}
					v=v.val;
				}
				if(v!==placeHolder){
					placeHolder=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//文本选择:
		Object.defineProperty(this, 'list', {
			get: function () {
				return list;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('list');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('list');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'list', hudView);
						valJXVMap.set('list', v);
					}
					v=v.val;
				}
				//更新选项
				function makeList(){
					let list,option;
					//删除旧选项
					list=self.webDataList;
					option=list.firstChild;
					while(option){
						list.removeChild(option);
						option=list.firstChild;
					}
					//设置新选项:
					v.forEach(function(item){
						option = document.createElement('option');
						option.value = item;
						list.appendChild(option);
					});
				}

				if(v!==list){
					list=v;
					if(v && !this.webDataList){
						//改变为ComboBox模式:
						let newWebObj,oldWebObj,item;
						oldWebObj=self.webObj;
						//创建选项Html节点:
						self.webDataList=document.createElement('datalist');
						self.webDataList.id="@DataList"+jaxEnv.genTimeHash();
						jaxEnv.jaxDiv.appendChild(self.webDataList);
						makeList();

						//创建新的控件，把它插入当前控件前面:
						newWebObj=document.createElement('input');
						self.webObj.parentNode.insertBefore(newWebObj,self.webObj);
						//让控件关联DataList:
						newWebObj.outerHTML='<input list="'+self.webDataList.id+'">';
						newWebObj=self.webObj.previousSibling;

						//复制样式:
						newWebObj.style.cssText=self.webObj.style.cssText;
						newWebObj.id=self.webObj.id;
						newWebObj.value=text;
						newWebObj.placeholder=placeHolder;
						newWebObj.jaxObj=self;

						//移动子控件
						item=oldWebObj.firstChild;
						while(item){
							oldWebObj.removeChild(item);
							newWebObj.appendChild(item);
							item=oldWebObj.firstChild;
						}
						oldWebObj.parentNode.removeChild(oldWebObj);

						//复制消息响应:
						newWebObj.onfocus=oldWebObj.onfocus;
						newWebObj.onblur=oldWebObj.onblur;
						newWebObj.oninput=oldWebObj.oninput;
						newWebObj.onkeyup=oldWebObj.onkeyup;

						this.webObj=newWebObj;
					}else if(!v && self.webDataList){
						//TODO: 隐藏DataList是否可以达到目的？
						self.webDataList.style.display="none";
					}else if(v){
						//DataList已经有了，直接更新选项后展示:
						makeList();
						self.webDataList.style.display="";
					}
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//字体名字:
		Object.defineProperty(this, 'font', {
			get: function () {
				return fntName;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('font');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('font');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'font', hudView);
						valJXVMap.set('font', v);
					}
					v=v.val;
				}
				if (v!==fntName) {
					fntName=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//字体颜色:
		Object.defineProperty(this, 'color', {
			get: function () {
				return color;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('color');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('color');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'color', hudView);
						valJXVMap.set('color', v);
					}
					v=v.val;
				}
				if (Array.isArray(v)) {
					fntColor[0] = v[0];
					fntColor[1] = v[1];
					fntColor[2] = v[2];
				} else if (typeof (v) === 'string') {
					[fntColor[0],fntColor[1],fntColor[2],fntColor[3]]=JAXEnv.parseColor(v);
				} else ;
				_attrChanged = 1;
				signUpdate();
			},
			enumerable: true
		});

		//字体尺寸:
		Object.defineProperty(this, 'fontSize', {
			get: function () {
				return fntSize;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('fontSize');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('fontSize');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'fontSize', hudView);
						valJXVMap.set('fontSize', v);
					}
					v=v.val;
				}
				if (v!==fntSize) {
					fntSize=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		Object.defineProperty(this, 'selectOnFocus', {
			get: function () {
				return selectOnFocus;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('selectOnFocus');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('selectOnFocus');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'selectOnFocus', hudView);
						valJXVMap.set('selectOnFocus', v);
					}
					v=v.val;
				}
				if (v!==selectOnFocus) {
					selectOnFocus=v;
				}
			},
			enumerable: true
		});

		Object.defineProperty(this, 'outline', {
			get: function () {
				return outline;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('outline');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('outline');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'outline', hudView);
						valJXVMap.set('outline', v);
					}
					v=v.val;
				}
				outline=v?1:0;
				if(v){
					this.webObj.style.outlineStyle="auto";
				}else {
					this.webObj.style.outlineStyle="none";
				}
			},
			enumerable: true
		});

		Object.defineProperty(this, 'spellCheck', {
			get: function () {
				return spellCheck;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('spellCheck');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('spellCheck');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'spellCheck', hudView);
						valJXVMap.set('spellCheck', v);
					}
					v=v.val;
				}
				spellCheck=v?1:0;
				this.webObj.spellcheck=!!v;
			},
			enumerable: true
		});

		//选中开始/光标位置
		Object.defineProperty(this,"selectionStart",{
			get: function ()
			{
				if(this.webObj){
					return this.webObj.selectionStart;
				}
				return 0;
			},
			enumerable: true
		});

		//选中结束：
		Object.defineProperty(this,"selectionEnd",{
			get: function ()
			{
				if(this.webObj){
					return this.webObj.selectionEnd;
				}
				return 0;
			},
			enumerable: true
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		this._syncWebObjAttr=function(){
			let webObj,style;
			webObj=this.webObj;
			if(webObj){
				style=webObj.style;
				style.backgroundColor="rgba("+colorBox+")";
				style.borderRadius=""+coner+"px";
				if(border!==0) {
					switch (borderStyle) {
						case 0:
						default:
							style.borderStyle = "solid";
							break;
						case 1:
							style.borderStyle = "dashed";
							break;
						case 2:
							style.borderStyle = "dotted";
							break;
					}
					style.borderWidth = "" + border + "px";
				}else {
					style.borderStyle = "none";
					style.borderWidth = "0px";
				}
				style.borderColor="RGBA("+colorBorder+")";

				//Input 相关:
				if(_textChanged) {
					_textChanged = 0;
					webObj.value = text;
				}
				if(placeHolder) {
					webObj.placeholder = placeHolder;
				}
				style.fontSize=fntSize+"px";
				if(fntName){
					style.fontFamily=fntName;
				}else {
					style.fontFamily="";
				}
				style.color="rgb("+fntColor+")";
			}
			_attrChanged=0;
		};
	}
};

JAXHudEditBox.prototype=__Proto$6;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudEditBox.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'bgColor','border','borderStyle','borderColor','coner',
		'text','font','color','fontSize',
		'placeHolder','list',
		'selectOnFocus','outline','spellCheck','inputType',
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('edit', function (env) {
		return new JAXHudEditBox(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$6.preApplyCSS = function (cssObj)
	{
		var div, father;
		var self=this;
		let jaxEnv=this.jaxEnv;
		let enterKeyTime=0;
		this.removeAllChildren();

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		if(!this.webObj) {
			div = this.webObj = document.createElement('input');
			div.type=cssObj.inputType||"text";
			div.style.position = cssObj.position||"absolute";
			div.style.boxSizing="border-box";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.onfocus=function(){
				if(self.selectOnFocus){
					self.selectAll();
				}
				if(self.OnFocus){
					self.OnFocus();
				}
				console.log("Focus");
			};
			div.onblur=function(){
				if(self.OnBlur){
					self.OnBlur();
				}
				console.log("Blur");
			};
			div.oninput=function(){
				if(self.OnInput){
					self.OnInput();
				}
			};
			div.onchange=function(e){
				let time;
				if(self.OnChange){
					time=Date.now()-enterKeyTime;
					if(time<30) {
						self.OnChange(e);
					}
				}
			};
			div.onkeydown=function(evt){
				if(evt.code==="Enter"){
					enterKeyTime=Date.now();
					if(self.OnUpdate){
						self.OnUpdate();
					}
				}else if(evt.code==="Escape"){
					if(self.OnCancel){
						self.OnCancel();
					}
				}
			};
			div.onkeyup=function(evt){
			};
			div.jaxObj = this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$6.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$6.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};

	//---------------------------------------------------------------
	//开始编辑
	__Proto$6.focus=__Proto$6.startEdit=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		if(this.poseChanged) {
			this._syncWebObj();
		}
		this.webObj.focus();
		if(this.selectOnFocus){
			this.selectAll();
		}
	};

	//---------------------------------------------------------------
	//结束编辑
	__Proto$6.endEdit=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		if(this.poseChanged) {
			this._syncWebObj();
		}
		this.webObj.blur();
	};

	//---------------------------------------------------------------
	//选中全部文本
	__Proto$6.selectAll=function(){
		if(this.attrChanged){
			this._syncWebObjAttr();
		}
		this.webObj.setSelectionRange(0,this.webObj.value.length);
	};

	//-----------------------------------------------------------------------
	//释放资源:
	__Proto$6.freeHud=function(){
		var father,div;
		this.removeAllChildren();
		father=this.father;
		div=this.webObj;
		if(div && father && father.webObj){
			father=div.parentNode;
			if(father){
				father.removeChild(div);
			}
			this.webObj=null;
		}
		//释放ComboBox选项:
		if(this.webDataList){
			this.jaxEnv.jaxDiv.removeChild(this.webDataList);
			this.webDataList=null;
		}
	};
}

var JAXHudScrollBox,__Proto$5;
var JAXHudScrollCell;

//***************************************************************************
//ScrollBox里面的一行
//***************************************************************************
JAXHudScrollCell=function(box,column=0)
{
	var self;
	self=this;
	this.jaxEnv=box.jaxEnv;
	this.owner=box;
	this.owner_=box;
	this.hud=null;
	this.webObj=this.webDiv=document.createElement('div');
	box.webObj.appendChild(this.webDiv);
	this.webDiv.style.width="100%";
	this.webDiv.style.position="relative";
	this.webDiv.style.marginBottom=box.subGap+"px";

	this.sizeObserver=new ResizeObserver(entries=>{
		let div;
		div=entries[0].target;
		self.webDiv.style.height=div.offsetHeight + "px";
	});

	Object.defineProperty(this, 'w', {
		get: function () {
			return box.w/(box.column>0?box.column:1);
		},
		enumerable: true
	});

	Object.defineProperty(this, 'h', {
		get: function () {
			return box.h;
		},
		enumerable: true
	});
	Object.defineProperty(this, 'clientW', {
		get: function () {
			return box.clientW/(box.column>0?box.column:1);
		},
		enumerable: true
	});

	Object.defineProperty(this, 'clientH', {
		get: function () {
			return box.clientH;
		},
		enumerable: true
	});

	Object.defineProperty(this, 'stateObj', {
		get: function () {
			return box.stateObj;
		},
		enumerable: true
	});


};

JAXHudScrollCell.prototype={};
//---------------------------------------------------------------------------
//设置Box的内容:
JAXHudScrollCell.prototype.setItem=function(obj)
{
	var hud;
	if(this.hud){
		this.sizeObserver.unobserve(this.hud.webObj);
		this.hud.release();
		this.hud.owner_=null;
	}
	if(obj.isJAXHudObj_){
		hud=obj;
	}else {
		hud=JAXHudObj.createHudByType(obj.type,this.jaxEnv,null,obj,this);
	}
	if(hud){
		this.hud=hud;
		if(hud.webObj) {
			this.webDiv.appendChild(hud.webObj);
			this.webDiv.style.height=hud.h+"px";
			this.sizeObserver.observe(hud.webObj);
		}
		this.hud.owner_=this;
	}
	return hud;
};

//---------------------------------------------------------------------------
//用来创建Hud
JAXHudScrollCell.prototype.appendChild=function(hud)
{
	hud.father_ = this;
	hud.hold();
	if(hud.webObj) {
		this.webDiv.appendChild(hud.webObj);
	}
};

//---------------------------------------------------------------------------
//用来创建Hud
JAXHudScrollCell.prototype.removeChild=function(hud)
{
	if(hud.father_!==this)
		return;
	if(hud.webObj) {
		this.webDiv.removeChild(hud.webObj);
	}
	hud.release();
	hud.father_ = null;
};

//---------------------------------------------------------------------------
//移除Box
JAXHudScrollCell.prototype.freeCell=function(obj)
{
	this.webDiv.parentNode.removeChild(this.webDiv);
	this.webDiv=null;
	if(this.hud){
		this.hud.release();
		this.hud.owner_=null;
		this.hud=null;
	}
	this.sizeObserver.disconnect();
};

//***************************************************************************
//ScrollBox定义
//***************************************************************************
__Proto$5=new JAXHudObj();
JAXHudScrollBox=function(jaxEnv)
{
	var subGap,self;
	var headSpace,endSpace;
	var _attrChanged;
	var signUpdate;
	var oldSubGap;
	var column=-1;

	self=this;
	this.subHudList_=[];
	this.subFrameDiv=null;
	this.subInnerDiv=null;

	//this.headSpaceDiv=null;
	//this.endSpaceDiv=null;
	this.subColumnDivs=[];

	var pxSubList=new Proxy(this.subHudList_,{
		get:function(obj,pName){
			switch(pName){
			case "push": {
				return function(css){
					var idx,hud;
					[idx,hud]=self.addSub(css);
					return hud;
				};
			}
			case "pop":
				return function(){
					self.removeSub(self.subHudList_.length-1,1);
				};
			case "splice":
				return function(idx,n,hud){
					if(n>0){
						self.removeSub(idx,n);
					}
					if(hud){
						self.insertSub(hud,idx);
					}
				};
			case "insert":
				return function(css,idx){
					return self.insertSub(css,idx);
				};
			case "moveUp":
				return function(idx){
					return self.subMoveUp(idx);
				};
			case "clear":
				return function(){
					self.removeSub(0,self.subHudList_.length);
				};
			case "indexOf":
				return function(hud){
					let list,i,n;
					list=self.subHudList_;
					n=list.length;
					for(i=0;i<n;i++){
						if(list[i].hud===hud)
							return i;
					}
					return -1;
				};
			}
			if(pName>=0 && pName<obj.length){
				return obj[pName].hud;
			}else if(pName==='length'){
				return obj.length;
			}
			return undefined;
		},
		set:function(obj,pName,v){}
	});


	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.clip=1;

	this.jaxClassFunc=JAXHudScrollBox;

	signUpdate=this.signUpdate;

	subGap=0;
	oldSubGap=0;
	headSpace=0;
	endSpace=50;
	_attrChanged=0;

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//-------------------------------------------------------------------
		//列的数量:
		Object.defineProperty(this,'column',{
			get:function () {
				return column;
			},
			set:function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('column');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('column');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'column', hudView);
						valJXVMap.set('column', v);
					}
					v=v.val;
				}
				var list,i,n,columnW;
				if(column===v)
					return;
				if(v<=0){
					console.warn("Colum number error: "+v);
					return;
				}
				list=this.subHudList_.slice(0);
				n=list.length;
				for(i=0;i<n;i++){
					list[i]=list[i].hud;
					list[i].hold();
				}
				this.clear();

				n=this.subColumnDivs.length;
				for(i=0;i<n;i++){
					this.subInnerDiv.removeChild(this.subColumnDivs[i]);
				}

				columnW=this.w/v;
				this.subColumnDivs=[];
				for(i=0;i<v;i++){
					let subDiv;
					subDiv=document.createElement('div');
					this.subInnerDiv.appendChild(subDiv);
					subDiv.style.position="relative";
					subDiv.style.width=columnW+"px";
					subDiv.style.height="auto";
					//subDiv.style.overflowX="hidden";
					this.subColumnDivs.push(subDiv);
				}

				n=list.length;
				for(i=0;i<n;i++){
					this.addSub(list[i]);
					list[i].release();
				}
				column=v;
				return v;
			},
			enumerable: true
		});
		//-------------------------------------------------------------------
		//顶部留白:
		Object.defineProperty(this, 'headSpace', {
			get: function () {
				return headSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('headSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('headSpace');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'headSpace', hudView);
						valJXVMap.set('headSpace', v);
					}
					v=v.val;
				}
				if (v!==headSpace) {
					headSpace=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//-------------------------------------------------------------------
		//底部留白:
		Object.defineProperty(this, 'endSpace', {
			get: function () {
				return endSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('endSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('endSpace');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'endSpace', hudView);
						valJXVMap.set('endSpace', v);
					}
					v=v.val;
				}
				if (v!==endSpace) {
					endSpace=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//-------------------------------------------------------------------
		//行间距:
		Object.defineProperty(this, 'subGap', {
			get: function () {
				return subGap;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('subGap');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('subGap');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'subGap', hudView);
						valJXVMap.set('subGap', v);
					}
					v=v.val;
				}
				if (v!==subGap) {
					subGap=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//-------------------------------------------------------------------
		//子节点列表控件:
		Object.defineProperty(this,'subs',{
			get:function(){
				return pxSubList;
			},
			set:function(list){
			},
			configurable:true
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		//---------------------------------------------------------------
		//删除全部滚动控件
		this.clear=this.removeAllSubs=function()
		{
			let list,i,n,box;
			list=this.subHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				box=list[i];
				box.freeCell();
			}
			list.splice(0);
		};

		//---------------------------------------------------------------
		//添加滚动控件
		this.addSub=function(obj)
		{
			let cell,idx,list,i,n,columnDiv,h,minColumn,minH;
			idx=this.subHudList_.length;
			if(Array.isArray(obj)){
				let list,i,n;
				list=obj;
				n=list.length;
				for(i=0;i<n;i++){
					this.addSub(list[i]);
				}
				return [idx,n];
			}
			idx=this.subHudList_.length;
			cell=new JAXHudScrollCell(this);

			//选一个列:
			list=this.subColumnDivs;
			minColumn=list[0];
			minH=10000000;
			n=list.length;
			for(i=0;i<n;i++){
				columnDiv=list[i];
				h=columnDiv.lastChild?(columnDiv.lastChild.offsetTop+columnDiv.lastChild.offsetHeight):0;
				if(h<minH){
					minH=h;
					minColumn=columnDiv;
				}
			}
			minColumn.appendChild(cell.webDiv);
			cell.setItem(obj);
			this.subHudList_.push(cell);
			return [idx,cell.hud];
		};

		//---------------------------------------------------------------
		//插入滚动控件
		this.insertSub=function(obj,idx)
		{
			let cell,oldCell,hud;
			if(idx<0)
				idx=0;
			if(Array.isArray(obj)){
				let list,i,n;
				list=obj;
				n=list.length;
				for(i=0;i<n;i++){
					this.insertSub(list[i],idx+i);
				}
				return n;
			}
			oldCell=this.subHudList_[idx];
			cell=new JAXHudScrollCell(this);
			if(oldCell) {
				cell=new JAXHudScrollCell(this);
				oldCell.webDiv.parentNode.insertBefore(cell.webDiv,oldCell.webDiv);
				cell.setItem(obj);
				this.subHudList_.splice(idx,0,cell);
				return cell.hud;
			}
			[hud,idx]=this.addSub(obj);
			return hud;
		};

		//---------------------------------------------------------------
		//移除滚动控件
		this.removeSub=function(idx,n)
		{
			let list,cell;
			if(n>1){
				let i;
				for(i=0;i<n;i++){
					this.removeSub(idx);
				}
				return;
			}
			list=this.subHudList_;
			if(idx<0 ||idx>=list.length)
				return;
			cell=list[idx];
			cell.freeCell();
			list.splice(idx,1);
		};

		//---------------------------------------------------------------
		//根据Id获得滚动控件
		this.findSubById=function(subId)
		{
			let list,cell,i,n;
			list=this.subHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				cell=list[i];
				if(cell && cell.hud && cell.hud.id===subId)
				{
					return cell.hud;
				}
			}
			return null;
		};

		//---------------------------------------------------------------
		//获得滚动控件的序号
		this.indexOfSub=function(hud)
		{
			let list,cell,i,n;
			list=this.subHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				cell=list[i];
				if(cell && cell.hud===hud){
					return i;
				}
			}
			return -1;
		};

		//---------------------------------------------------------------
		//获得指定序号的滚动控件
		this.subAtIdex=function(idx)
		{
			let list,cell;
			list=this.subHudList_;
			if(idx<0 || idx>=list.length)
				return null;
			cell=list[idx];
			if(cell)
				return cell.hud;
			return null;
		};

		//---------------------------------------------------------------
		//一个Sub向上移动:
		this.subMoveUp=function(idx){
			var cell,list,preCell;
			list=this.subHudList_;
			if(idx<=0 || idx>=list.length){
				return 0;
			}
			cell=list[idx];
			preCell=list[idx-1];
			list.splice(idx,1);
			list.splice(idx-1,0,cell);
			cell.webDiv.parentNode.removeChild(cell.webDiv);
			preCell.webDiv.parentNode.insertBefore(cell.webDiv,preCell.webDiv);
			return 1;
		};

		//---------------------------------------------------------------
		//重新排列Subs:
		this.relayoutSubs=function(start=0){
			var list,i,n;
			list=this.subHudList_.slice(0);
			n=list.length;
			start=start>0?start:0;
			for(i=start;i<n;i++){
				list[i]=list[i].hud;
				list[i].hold();
			}
			if(start>0){
				this.removeSub(start,n-start);
			}else {
				this.clear();
			}
			for(i=start;i<n;i++){
				this.addSub(list[i]);
				list[i].release();
			}
		};

		//---------------------------------------------------------------
		//更新滚动控件
		this._applySubHuds=function(list)
		{
			this.clear();
			this.addSub(list);
		};

		//-------------------------------------------------------------------
		//同步控件属性:
		this._syncWebObjAttr=function()
		{
			let webObj,subDiv,list,i,n,cell;
			webObj=this.webObj;
			if(!webObj) {
				return;
			}
			subDiv=this.subFrameDiv;
			subDiv.style.paddingTop=this.headSpace+"px";
			subDiv.style.paddingBottom=this.endSpace+"px";
			this.subInnerDiv.style.width=this.size[0]+"px";
			if(oldSubGap!==subGap){
				list=this.subHudList_;
				n=list.length;
				for(i=0;i<n;i++){
					cell=list[i];
					cell.webDiv.style.marginBottom=subGap+"px";
				}
				oldSubGap=subGap;
			}
			_attrChanged=0;
		};

		//-------------------------------------------------------------------
		//在全部子节点（包含subs）里执行一个函数:
		this.execInTree=function(func){
			var list,i,n,hud;
			list=this.subHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				hud=list[i].hud;
				if(hud && func(hud)){
					return;
				}
			}
			list=this.chdHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				if(func(list[i])){
					return;
				}
			}
		};

	}
};

JAXHudScrollBox.prototype=__Proto$5;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudScrollBox.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'column','headSpace','endSpace','subGap','subs',
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('scroll', function (env) {
		return new JAXHudScrollBox(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$5.preApplyCSS = function (cssObj)
	{
		var div, father, subDiv,innerDiv;
		let jaxEnv=this.jaxEnv;

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		this.removeAllChildren();
		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;

			//创建滚动框架div:
			subDiv=this.subFrameDiv = document.createElement('div');
			div.appendChild(subDiv);
			subDiv.style.position="absolute";
			subDiv.style.left="0px";
			subDiv.style.top="0px";
			subDiv.style.width="100%";
			subDiv.style.height="100%";
			subDiv.style.overflowY="scroll";
			subDiv.style.overflowX="hidden";
			subDiv.style.boxSizing="border-box";

			//创建内部框架:
			innerDiv=this.subInnerDiv = document.createElement('div');
			subDiv.appendChild(innerDiv);
			innerDiv.style.position="relative";
			innerDiv.style.width="100%";
			innerDiv.style.height="auto";
			innerDiv.style.display="flex";

			//监视innerDiv的尺寸:
			let showScrollBar=0;
			this.innerSizeObserver=new ResizeObserver(entries=>{
				let div,h;
				div=entries[0].target;
				h=div.offsetHeight;
				if(h>subDiv.offsetHeight){
					if(!showScrollBar) {
						subDiv.style.overflowY = "scroll";
						showScrollBar = 1;
					}
				}else if(showScrollBar){
					showScrollBar=0;
					subDiv.style.overflowY="hidden";
					subDiv.scrollTop=0;
				}
			});
			this.innerSizeObserver.observe(innerDiv);
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS把pptList赋值后
	__Proto$5.finApplyCSS = function (cssObj)
	{
		if(this.webObj){
			this.webObj.id=this.id;
		}
		this.items2Add_=cssObj.items;
		this.subs2Add_=cssObj.subs;
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$5.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		delete this.items2Add_;
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		//确保有列div:
		if(!cssObj.column>=1){
			this.column=1;
		}

		list=this.subs2Add_;
		if(Array.isArray(list)){
			this._applySubHuds(list);
		}
		delete this.subs2Add_;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$5.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};

}

var JAXHudTree,__Proto$4;
var JAXHudTreeNode;

//***************************************************************************
//TreeBox里面的一行
//***************************************************************************
{
	JAXHudTreeNode = function (box, obj, intend_, ownerNode)
	{
		var intend,self;

		self=this;
		intend = intend_;
		this.ownerNode=ownerNode;
		this.nodeObj = obj;
		this.jaxEnv = box.jaxEnv;
		this.owner = box;
		this.owner_=box;
		this.hud = null;
		this.webObj = this.webDiv = document.createElement('div');
		box.webObj.appendChild(this.webDiv);
		this.webDiv.id="TreeNode";
		this.webDiv.style.width = "100%";
		this.webDiv.style.position = "relative";
		this.webDiv.style.marginBottom=box.nodeGap+"px";
		//this.webDiv.style.left=(intend*box.intend)+"px";
		this.subIntend=0;
		if(ownerNode) {
			this.intendW = ownerNode.intendW + (ownerNode.subIntend ? ownerNode.subIntend : box.intend);
		}else {
			this.intendW=0;
		}
		this.isOpen=0;
		this.sizeObserver=new ResizeObserver(entries=>{
			let hud;
			hud=entries[0].target;
			self.webDiv.style.height=hud.offsetHeight + "px";
			box.checkScroll();
		});

		Object.defineProperty(this, 'w', {
			get: function () {
				return box.w;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'h', {
			get: function () {
				return box.h;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'clientW', {
			get: function () {
				return box.clientW;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'clientH', {
			get: function () {
				return box.clientH;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'stateObj', {
			get: function () {
				return box.stateObj;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'intend', {
			get: function () {
				return intend;
			},
			set: function (v) {
				intend = v;
				this.webDiv.style.left = (intend * box.intend) + "px";
			},
			enumerable: true
		});
	};

	JAXHudTreeNode.prototype = {};
	//---------------------------------------------------------------------------
	//设置Box的内容:
	JAXHudTreeNode.prototype.setItem = function (obj) {
		var hud;
		if(this.hud){
			this.sizeObserver.unobserve(this.hud.webObj);
			this.hud.release();
			hud.owner_=null;
		}
		if (obj.isJAXHudObj_) {
			hud = obj;
			hud.hold();
			hud.owner_=this;
		} else {
			hud = JAXHudObj.createHudByType(obj.type, this.jaxEnv, null, obj, this);
		}
		if (hud) {
			this.hud = hud;
			if (hud.webObj) {
				this.webDiv.appendChild(hud.webObj);
				this.webDiv.style.height = hud.h + "px";
			}
			if(hud.autoLayout){
				hud._doLayout();
			}
			this.sizeObserver.observe(hud.webObj);
		}
	};

	//---------------------------------------------------------------------------
	//用来创建Hud
	JAXHudTreeNode.prototype.appendChild = function (hud) {
		hud.father_ = this;
		hud.hold();
		if (hud.webObj) {
			this.webDiv.appendChild(hud.webObj);
		}
	};

	//---------------------------------------------------------------------------
	//用来创建Hud
	JAXHudTreeNode.prototype.removeChild = function (hud) {
		if (hud.father_ !== this)
			return;
		if (hud.webObj) {
			this.webDiv.removeChild(hud.webObj);
		}
		hud.release();
		hud.father_ = null;
	};

	//---------------------------------------------------------------------------
	//移除Box
	JAXHudTreeNode.prototype.freeNode = function () {
		//回调函数:
		if(this.owner.OnFreeNode){
			this.owner.OnFreeNode(this);
		}
		//移除Node:
		this.owner.subHudDiv.removeChild(this.webDiv);
		this.webDiv = null;
		if (this.hud) {
			this.hud.release();
			this.hud.owner_ = null;
			this.hud = null;
		}
		this.sizeObserver.disconnect();
		this.owner=null;
	};

	//---------------------------------------------------------------------------
	//暂时脱离控件树
	JAXHudTreeNode.prototype.detach = function () {
		this.owner.subHudDiv.removeChild(this.webDiv);
	};

	//---------------------------------------------------------------------------
	//重新加回控件树
	JAXHudTreeNode.prototype.attachBack = function (beforeNode) {
		if(beforeNode){
			this.owner.subHudDiv.insertBefore(this.webDiv,beforeNode.webDiv);
		}else {
			this.owner.subHudDiv.appendChild(this.webDiv);
		}
	};
}

//***************************************************************************
//树结构的Hud控件
//***************************************************************************
__Proto$4=new JAXHudObj();
JAXHudTree=function(jaxEnv)
{
	var self;
	var nodeCSSFunc;
	var subObjsFunc;
	var selNodes;
	var hotNode;
	var multi;
	var nodeGap;
	var oldNodeGap;
	var headSpace,endSpace;
	var nodeList;
	var signUpdate;
	var intend;
	var oldIntend;
	var _attrChanged;
	var showScroll;

	self=this;
	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.clip=1;
	this.jaxClassFunc=JAXHudTree;

	nodeCSSFunc=null;
	subObjsFunc=null;
	selNodes=new Set();
	hotNode=null;
	multi=0;
	intend=30;
	oldIntend=30;
	nodeGap=0;
	oldNodeGap=0;
	headSpace=0;
	endSpace=50;
	this.nodeList_=nodeList=[];
	signUpdate=this.signUpdate;
	showScroll=0;

	this.OnHotNodeChange=null;
	this.OnNodeOpen=null;
	this.OnNodeClose=null;
	this.OnAddNode=null;
	this.OnInsertNode=null;
	this.OnSelNodeChange=null;
	this.OnFreeNode=null;
	this.OnMoveNode=null;

	_attrChanged=0;

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	var pxNodeList=new Proxy(nodeList,{
		get:function(obj,pName){
			switch(pName){
				case "indexOf":
				case "every":
				case "filter":
				case "find":
				case "findIndex":
				case "forEach":
					return obj[pName];
			}
			if(pName>=0 && pName<obj.length){
				return obj[pName];
			}else if(pName==='length'){
				return obj.length
			}
			return undefined;
		},
		set:function(obj,pName,v){}
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//---------------------------------------------------------------
		//顶部留白:
		Object.defineProperty(this, 'intend', {
			get: function () {
				return intend;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('intend');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('intend');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'intend', hudView);
						valJXVMap.set('intend', v);
					}
					v=v.val;
				}
				if (v !== intend) {
					intend = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//项目间距:
		Object.defineProperty(this, 'nodeGap', {
			get: function () {
				return nodeGap;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('nodeGap');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('nodeGap');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'nodeGap', hudView);
						valJXVMap.set('nodeGap', v);
					}
					v=v.val;
				}
				if (v !== nodeGap) {
					nodeGap = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//顶部留白:
		Object.defineProperty(this, 'headSpace', {
			get: function () {
				return headSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('headSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('headSpace');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'headSpace', hudView);
						valJXVMap.set('headSpace', v);
					}
					v=v.val;
				}
				if (v !== headSpace) {
					headSpace = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//底部留白:
		Object.defineProperty(this, 'endSpace', {
			get: function () {
				return endSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('endSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('endSpace');
					}
					if(v.traces!==0) {
						v.trace(this.stateObj, this, 'endSpace', hudView);
						valJXVMap.set('endSpace', v);
					}
					v=v.val;
				}
				if (v!==endSpace) {
					endSpace=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//子节点列表控件:
		Object.defineProperty(this,'nodes',{
			get:function(){
				return pxNodeList;
			},
			set:function(list){
				//这里什么都不干
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//生成子节点CSS的函数:
		Object.defineProperty(this,'nodeCSS',{
			get:function(){
				return nodeCSSFunc;
			},
			set:function(v){
				nodeCSSFunc=v;
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//获得子节点列表的CSS的函数:
		Object.defineProperty(this,'getSubObjs',{
			get:function(){
				return subObjsFunc;
			},
			set:function(v){
				subObjsFunc=v;
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//当前的焦点节点:
		Object.defineProperty(this, 'hotNode', {
			get: function () {
				return hotNode;
			},
			set: function (v) {
				if (v!==hotNode && v instanceof JAXHudTreeNode) {
					this.setHotNode(v);
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//当前的选中节点列表:
		Object.defineProperty(this, 'selected', {
			get: function () {
				return selNodes;
			},
			set: function (v) {
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//允许多重选择:
		Object.defineProperty(this, 'multiSelect', {
			get: function () {
				return multi;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('intend');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('intend');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'intend', hudView);
						valJXVMap.set('intend', v);
					}
					v=v.val;
				}
				if(v!==multi){
					multi=v;
					this.clearSelects();
				}
			},
			enumerable: true
		});

		//控件客户区域宽度
		Object.defineProperty(this, 'clientW', {
			get: function () {
				return this.subHudDiv?this.subHudDiv.clientWidth:this.size[0];
			},
			set: function (v) {
				return v;
			},
			enumerable: true,
			configurable:true
		});
	}

	//***********************************************************************
	//不会被继承的函数:
	//***********************************************************************
	{
		//*******************************************************************
		//节点管理/访问:
		//*******************************************************************
		{
			let pauseSelCallback=0;
			let willOpenNodes=[];
			//---------------------------------------------------------------
			//删除全部滚动控件
			this.clear = this.removeAllNodes = function () {
				let list, i, n, node;
				hotNode = null;
				n=selNodes.size;
				selNodes.clear();
				if(n>0){
					if(!pauseSelCallback) {
						this.OnSelNodeChange && this.OnSelNodeChange();
					}
				}
				list = nodeList;
				n = list.length;
				for (i = 0; i < n; i++) {
					node = list[i];
					//this.subHudDiv.removeChild(node.webDiv);
					node.freeNode();
				}
				list.splice(0);
				this.checkScroll();
			};

			//---------------------------------------------------------------
			//在指定节点下添加节点，如果指定节点不存在，则添加根节点
			this.addNode = function (obj, upNode, hud) {
				let node, idx, css, i, n, intend, nextNode;
				//添加一个节点，先看看有没有父节点:
				if (!upNode) {
					//添加根节点
					node = new JAXHudTreeNode(this, obj, 0, null);
					this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
					css = hud ? hud : nodeCSSFunc(obj, node, this);
					node.setItem(css);
					nodeList.push(node);
					if (this.OnAddNode) {
						this.OnAddNode(obj, node, hud, upNode);
					}
					return node;
				}

				//在指定父节点下面添加子控件:
				idx = nodeList.indexOf(upNode);
				if (idx < 0) {
					return this.addNode(obj, null, hud);
				}
				intend = upNode.intend + 1;
				n = nodeList.length;
				findIdx:{
					for (i = idx + 1; i < n; i++) {
						if (nodeList[i].intend < intend) {
							idx = i;
							break findIdx;
						}
					}
					idx = -1;
				}

				//插入Node:
				nextNode = nodeList[idx];
				node = new JAXHudTreeNode(this, obj, intend, upNode);
				if (nextNode) {
					nodeList.splice(idx, 0, node);
					this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
				} else {
					nodeList.push(node);
					this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
				}
				css = hud ? hud : nodeCSSFunc(obj, node, this);
				node.setItem(css);
				if (this.OnAddNode) {
					this.OnAddNode(obj, node, upNode);
				}
				return node;
			};

			//---------------------------------------------------------------
			//在指定节点下添加一组节点，如果指定节点不存在，则添加到根节点
			this.addNodes = function (list, upNode) {
				let node, idx, css, obj, i, n, intend, nextNode;
				node=null;
				//添加一个节点，先看看有没有父节点:
				if (!upNode) {
					//添加根节点
					n = list.length;
					for (i = 0; i < n; i++) {
						obj = list[i];
						if(obj===true){//刚刚加入的节点要打开
							if(node){
								this.openNode(node);
							}
						}else {
							node = new JAXHudTreeNode(this, obj, 0, upNode);
							this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
							css = nodeCSSFunc(obj, node, this);
							node.setItem(css);
							nodeList.push(node);
							if (this.OnAddNode) {
								this.OnAddNode(obj, node, upNode);
							}
						}
					}
					return;
				}

				//在指定父节点下面添加子控件:
				idx = nodeList.indexOf(upNode);
				if (idx < 0) {
					return this.addNodes(list, null);
				}
				intend = upNode.intend + 1;
				n = nodeList.length;
				findIdx:{
					for (i = idx + 1; i < n; i++) {
						if (nodeList[i].intend !== intend) {
							idx = i;
							break findIdx;
						}
					}
					idx = -1;
				}

				node=null;
				willOpenNodes.splice(0);
				//插入Node:
				nextNode = nodeList[idx];
				n = list.length;
				for (i = 0; i < n; i++) {
					obj = list[i];
					if(obj===true){
						if(node) {
							willOpenNodes.push(node);
						}
					}else {
						node = new JAXHudTreeNode(this, obj, intend, upNode);
						if (nextNode) {
							nodeList.splice(idx, 0, node);
							this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
						} else {
							nodeList.push(node);
							this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
						}
						css = nodeCSSFunc(obj, node, this);
						node.setItem(css);
						idx++;
						if (this.OnAddNode) {
							this.OnAddNode(obj, node, upNode);
						}
					}
				}
				n=willOpenNodes.length;
				for(i=0;i<n;i++){
					this.openNode(willOpenNodes[i]);
				}
				willOpenNodes.splice(0);
			};

			//---------------------------------------------------------------
			//在指定节点(upNode)下的指定子节点位置(idx)插入对象为obj的一个节点,
			this.insertNode = function (idx, obj, upNode, hud) {
				let node, css, i, n, intend, nextNode, stIdx, atIdx, cnt;
				//添加一个节点，先看看有没有父节点:
				if (!upNode) {
					//添加根节点
					nextNode = nodeList[idx];
					node = new JAXHudTreeNode(this, obj, 0, null);
					if (!nextNode) {
						this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
						nodeList.push(node);
					} else {
						this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
						nodeList.splice(idx, 0, node);
					}
					css = hud ? hud : nodeCSSFunc(obj, node, this);
					node.setItem(css);
					if (this.OnInsertNode) {
						this.OnInsertNode(idx, obj, node, upNode);
					}
					return node;
				}

				//在指定父节点下面添加子控件:
				stIdx = nodeList.indexOf(upNode);
				if (stIdx < 0) {
					return this.insertNode(idx, obj, null, hud);
				}
				if (!upNode.isOpen) {
					this.openNode(upNode);
				}
				intend = upNode.intend + 1;
				n = nodeList.length;
				cnt = 0;
				if (idx > 0) {
					findIdx:{
						for (i = stIdx + 1; i < n; i++) {
							if (nodeList[i].intend === intend) {
								cnt++;
								if (cnt === idx + 1) {
									atIdx = i;
									break findIdx;
								}
							}
							if (nodeList[i].intend < intend) {
								atIdx = i;
								break findIdx;
							}
						}
						atIdx = i;
					}
				} else {
					atIdx = stIdx + 1;
				}

				//插入Node:
				nextNode = nodeList[atIdx];
				node = new JAXHudTreeNode(this, obj, intend, upNode);
				if (nextNode) {
					nodeList.splice(atIdx, 0, node);
					this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
				} else {
					nodeList.push(node);
					this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
				}
				css = hud ? hud : nodeCSSFunc(obj, node, this);
				node.setItem(css);
				if (this.OnInsertNode) {
					this.OnInsertNode(idx, obj, node, upNode);
				}
				return node;
			};

			//---------------------------------------------------------------
			//在指定节点前的位置插入对象为obj的一个同级节点,
			this.insertNodeBefore = function (obj, beforeNode, hud) {
				let idx,upNode,node, css, intend, nextNode;
				//添加一个节点，先看看有没有父节点:
				upNode=beforeNode.ownerNode;
				nextNode=beforeNode;
				idx=nodeList.indexOf(beforeNode);
				if (!upNode) {
					//添加根节点
					node = new JAXHudTreeNode(this, obj, 0, null);
					if (!nextNode) {
						this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
						nodeList.push(node);
					} else {
						this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
						nodeList.splice(idx, 0, node);
					}
					css = hud ? hud : nodeCSSFunc(obj, node, this);
					node.setItem(css);
					if (this.OnInsertNode) {
						this.OnInsertNode(idx, obj, node, upNode);
					}
					return node;
				}

				intend = upNode.intend + 1;

				//插入Node:
				node = new JAXHudTreeNode(this, obj, intend, upNode);
				if (nextNode) {
					nodeList.splice(idx, 0, node);
					this.subHudDiv.insertBefore(node.webDiv, nextNode.webDiv);
				} else {
					nodeList.push(node);
					this.subHudDiv.insertBefore(node.webDiv, this.endSpaceDiv);
				}
				css = hud ? hud : nodeCSSFunc(obj, node, this);
				node.setItem(css);
				if (this.OnInsertNode) {
					this.OnInsertNode(idx, obj, node, upNode);
				}
				return node;
			};

			//---------------------------------------------------------------
			//替换节点
			this.replaceNode = function (newNodeObj, oldNode, hud) {
				let idx, ownerNode, intend, node, css;
				idx = nodeList.indexOf(oldNode);
				if (idx < 0) {
					//TODO:
					throw "Old node is not in tree!.";
				}
				ownerNode = oldNode.ownerNode;
				intend = ownerNode.intend + 1;
				node = new JAXHudTreeNode(this, newNodeObj, intend, ownerNode);
				this.subHudDiv.insertBefore(node.webDiv, oldNode.webDiv);
				css = hud ? hud : nodeCSSFunc(newNodeObj, node, this);
				node.setItem(css);
				if (oldNode === hotNode) {
					this.setHotNode(node);
				}
				if (selNodes.has(oldNode)) {
					selNodes.delete(oldNode);
					selNodes.add(node);
					node.hud.showFace("selected");
					if(!pauseSelCallback) {
						this.OnSelNodeChange && this.OnSelNodeChange();
					}
				}
				nodeList.splice(idx, 1, node);
				oldNode.freeNode();
				this.checkScroll();
				return node;
			};

			//---------------------------------------------------------------
			//删除节点
			this.removeNode = function (nodeNode) {
				var node, idx;
				node = nodeNode;
				idx = nodeList.indexOf(node);
				if (idx < 0)
					return;
				if (node === hotNode) {
					this.setHotNode(null);
				}
				this.closeNode(nodeNode);
				if(selNodes.has(nodeNode)) {
					selNodes.delete(nodeNode);
					if(!pauseSelCallback) {
						this.OnSelNodeChange && this.OnSelNodeChange();
					}
				}
				nodeList.splice(idx, 1);
				node.freeNode();
				this.checkScroll();
			};

			//---------------------------------------------------------------
			//得到节点的Hud控件:
			this.getNodeHud = function (node) {
				return node.hud;
			};

			//---------------------------------------------------------------
			//得到Obj对应的节点:
			this.getNodeOfObj = function (obj) {
				let idx;
				let isNode = (node) => node.nodeObj === obj;
				idx = nodeList.findIndex(isNode);
				if (idx < 0)
					return null;
				return nodeList[idx];
			};

			//---------------------------------------------------------------
			//打开一个节点:
			this.openNode = function (nodeNode) {
				let list, nodeObj;
				if (!subObjsFunc)
					return;
				if (nodeNode.isOpen)
					return;
				nodeObj = nodeNode.nodeObj;
				list = subObjsFunc(nodeObj, nodeNode);
				if (!Array.isArray(list) || !list.length) {
					nodeNode.isOpen = 1;
					nodeNode.hud.showFace("open");
					return;
				}
				nodeNode.isOpen = 1;
				this.addNodes(list, nodeNode);
				nodeNode.hud.showFace("open");
			};

			//---------------------------------------------------------------
			//关闭一个节点:
			this.closeNode = function (nodeNode) {
				let idx, node, n, intend;
				n = nodeList.length;
				node = nodeNode;
				idx = nodeList.indexOf(node);
				if (idx < 0)
					return;
				nodeNode.isOpen = 0;
				nodeNode.hud.showFace("close");
				intend = node.intend + 1;
				idx += 1;
				node = nodeList[idx];
				if (!node || node.intend !== intend) {
					//没有打开
					return;
				}
				for (; idx < n; idx++) {
					node = nodeList[idx];
					if (node && node.intend >= intend) {
						nodeList.splice(idx, 1);
						if (node === hotNode) {
							this.setHotNode(null);
						}
						if(selNodes.has(node)) {
							selNodes.delete(node);
							if(!pauseSelCallback) {
								this.OnSelNodeChange && this.OnSelNodeChange();
							}
						}
						node.freeNode();
						idx--;
						n--;
					} else {
						this.checkScroll();
						return;
					}
				}
				this.checkScroll();
			};

			//---------------------------------------------------------------
			//设置当前高亮节点:
			this.setHotNode = function (node,addSel=0) {
				if (node === hotNode) {
					return;
				}
				if (hotNode) {
					if (selNodes.has(hotNode)) {
						hotNode.hud.face = "selected";
					} else {
						hotNode.hud.face = "normal";
					}
				}
				hotNode = node;
				if (node) {
					if (multi && addSel) {
						selNodes.add(node);
						if(!pauseSelCallback) {
							this.OnSelNodeChange && this.OnSelNodeChange();
						}
					} else {
						pauseSelCallback++;
						this.clearSelects();
						pauseSelCallback--;
						selNodes.add(node);
						if(!pauseSelCallback) {
							this.OnSelNodeChange && this.OnSelNodeChange();
						}
					}
					node.hud.face = "hot";
				} else {
					if (!multi || !addSel) {
						this.clearSelects();
					}
				}
				if (this.OnHotNodeChange) {
					this.OnHotNodeChange(hotNode);
				}
			};

			//---------------------------------------------------------------
			//清除全部的选中节点
			this.clearSelects = function () {
				var node;
				for (node of selNodes) {
					node.hud.face = "normal";
				}
				if(selNodes.size>0) {
					selNodes.clear();
					if (hotNode) {
						hotNode.face = "hot";
					}
					if(!pauseSelCallback){
						this.OnSelNodeChange&&this.OnSelNodeChange();
					}
				}
			};

			//---------------------------------------------------------------
			//选中节点
			this.selectNode = function (nodeNode) {
				selNodes.add(nodeNode);
				if (nodeNode !== hotNode) {
					nodeNode.hud.face = "selected";
				}
				if(!pauseSelCallback){
					this.OnSelNodeChange&&this.OnSelNodeChange();
				}
			};

			//---------------------------------------------------------------
			//取消选中节点
			this.deselectNode = function (nodeNode) {
				if(selNodes.has(nodeNode)) {
					selNodes.delete(nodeNode);
					if (nodeNode !== hotNode) {
						nodeNode.hud.face = "normal";
					}
					if(!pauseSelCallback){
						this.OnSelNodeChange&&this.OnSelNodeChange();
					}
				}
			};

			//---------------------------------------------------------------
			//节点是否被选中
			this.isNodeSelected=function(node){
				return selNodes.has(node);
			};

			//---------------------------------------------------------------
			//找到一个节点
			this.findNode = function (func) {
				var node;
				for (node of nodeList) {
					if (func(node)) {
						return node;
					}
				}
				return null;
			};

			//---------------------------------------------------------------
			//获得节点的总数:
			this.getNodeNum = function () {
				return nodeList.length;
			};

			//---------------------------------------------------------------
			//获得一个节点的序号:
			this.indexOfNode = function (node) {
				return nodeList.indexOf(node);
			};

			//---------------------------------------------------------------
			//向上移动一个节点:
			this.moveNodeUp = function (node) {
				var idx, intend, preNode, preIdx, isOpen;
				var nxtIdx, nxtNode;
				idx = nodeList.indexOf(node);
				preIdx = idx - 1;
				nxtIdx = idx + 1;
				preNode = nodeList[preIdx];
				if (!preNode) {
					return 0;
				}
				isOpen = node.isOpen;
				intend = node.intend;
				//移动的节点先关闭
				this.closeNode(node);
				while (preNode.intend > intend) {
					preIdx--;
					preNode = nodeList[preIdx];
				}
				if (preNode.intend !== intend) {
					return 0;
				}
				node.detach();
				nodeList.splice(idx, 1);
				node.attachBack(preNode);
				nodeList.splice(preIdx, 0, node);
				//把子节点也上移
				if (isOpen) {
					nxtNode = nodeList[nxtIdx];
					while (nxtNode && nxtNode.intend > intend) {
						preIdx += 1;
						nxtNode.detach();
						nodeList.splice(nxtIdx, 1);
						nxtNode.attachBack(node);
						nodeList.splice(preIdx, 0, nxtNode);
						node = nxtNode;
						nxtIdx += 1;
						nxtNode = nodeList[nxtIdx];
					}
				}
				if(this.OnMoveNode){
					this.OnMoveNode();
				}
				return 1;
			};

			//---------------------------------------------------------------
			//在全部子节点（包含subs）里执行一个函数:
			this.execInTree = function (func) {
				var list, i, n, hud;
				list = nodeList;
				n = list.length;
				for (i = 0; i < n; i++) {
					hud = list[i].hud;
					if (hud && func(hud)) {
						return;
					}
				}
				list = this.chdHudList_;
				n = list.length;
				for (i = 0; i < n; i++) {
					if (func(list[i])) {
						return;
					}
				}
			};
		}

		//---------------------------------------------------------------
		//当控件尺寸发生变化，调用这个函数
		this._sizeChanged=function(){
			let list,i,n,hud;
			list=nodeList;
			n=list.length;
			for(i=0;i<n;i++){
				hud=list[i].hud;
				if(hud.autoLayout){
					hud._doLayout();
				}
			}
			self.OnSizeChanged&&self.OnSizeChanged();
		};


		//---------------------------------------------------------------
		//CheckScroll
		this.checkScroll=function(){
			var div,h;
			div=this.endSpaceDiv;
			h=div.offsetTop+div.offsetHeight;
			if(h>this.webObj.offsetHeight){
				if(!showScroll){
					this.subHudDiv.style.overflowX="hidden";
					this.subHudDiv.style.overflowY="scroll";
					showScroll=1;
					this._sizeChanged();
				}
			}else if(showScroll){
				this.subHudDiv.style.overflowX="hidden";
				this.subHudDiv.style.overflowY="hidden";
				showScroll=0;
				this.subHudDiv.scrollTop=0;
				this._sizeChanged();
			}
		};

		//---------------------------------------------------------------
		//同步控件属性:
		this._syncWebObjAttr = function () {
			let webObj, list, i, n, node;
			webObj = this.webObj;
			if (!webObj) {
				return;
			}
			this.endSpaceDiv.style.height = this.endSpace + "px";
			this.headSpaceDiv.style.height = this.headSpace + "px";
			this.checkScroll();
			if (oldNodeGap !== nodeGap) {
				list = nodeList;
				n = list.length;
				for (i = 0; i < n; i++) {
					node = list[i];
					node.webDiv.style.marginBottom = nodeGap + "px";
				}
				oldNodeGap = nodeGap;
			}
			if (oldIntend !== intend) {
				list = nodeList;
				n = list.length;
				for (i = 0; i < n; i++) {
					node = list[i];
					node.intend = intend;
				}
				oldIntend = intend;
			}
			_attrChanged = 0;
		};

	}
};

JAXHudTree.prototype=__Proto$4;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudTree.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'intend','nodeGap','headSpace','endSpace','nodeCSS','getSubObjs','multiSelect',
		'OnHotNodeChange','OnNodeOpen','OnNodeClose','OnAddNode','OnInsertNode','OnSelNodeChange',
		'OnFreeNode','OnMoveNode',
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('tree', function (env) {
		return new JAXHudTree(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$4.preApplyCSS = function (cssObj)
	{
		var div, father, subDiv;
		let jaxEnv=this.jaxEnv;

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		this.removeAllChildren();
		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;

			//创建滚动框架div:
			subDiv=this.subHudDiv = document.createElement('div');
			div.appendChild(subDiv);
			subDiv.style.position="absolute";
			subDiv.style.left="0px";
			subDiv.style.top="0px";
			subDiv.style.width="100%";
			subDiv.style.height="100%";
			subDiv.style.overflowY="hidden";
			subDiv.style.overflowX="hidden";

			this.headSpaceDiv = document.createElement('div');
			this.headSpaceDiv.style.position="relative";
			this.headSpaceDiv.style.width="100%";
			subDiv.appendChild(this.headSpaceDiv);

			this.endSpaceDiv = document.createElement('div');
			this.endSpaceDiv.style.position="relative";
			this.endSpaceDiv.style.width="100%";
			subDiv.appendChild(this.endSpaceDiv);
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS把pptList赋值后
	__Proto$4.finApplyCSS = function (cssObj)
	{
		if(this.webObj){
			this.webObj.id=this.id;
		}
		this.items2Add_=cssObj.items;
		this.nodes2Add_=cssObj.nodes;
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$4.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		this.items2Add_=null;
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._syncWebObjAttr();
		this._holdAttr=false;
		list=this.nodes2Add_;
		if(Array.isArray(list)){
			this.addNodes(list,null);
		}
		delete this.nodes2Add_;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
		// if(cssObj.jaxObjHash){
		// 	this.jaxEnv.popObjHasher(this);
		// }
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$4.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};
}

var JAXHudList,__Proto$3;
var JAXHudListNode;

//***************************************************************************
//ListBox里面的一行
//***************************************************************************
{
	JAXHudListNode = function (box, obj, beforeNode)
	{
		var colNum,i,div,columns,css,hud;

		columns=box.columns;
		if(!columns){
			columns=[box.w];
		}
		this.columns=columns;
		colNum = columns.length;


		Object.defineProperty(this, 'w', {
			get: function () {
				return this.curColumn?this.columns[this.curColumn]:this.owner.w;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'h', {
			get: function () {
				return box.rowH;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'clientW', {
			get: function () {
				return this.curColumn?this.columns[this.curColumn]:this.owner.clientW;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'clientH', {
			get: function () {
				return box.rowH;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'stateObj', {
			get: function () {
				return box.stateObj;
			},
			enumerable: true
		});

		Object.defineProperty(this, 'hud', {
			get: function () {
				return this.columnHuds[0];
			},
			enumerable: true
		});

		this.nodeObj = obj;
		this.jaxEnv = box.jaxEnv;
		this.owner = box;
		this.owner_=box;
		this.webObj = this.webDiv = null;
		this.columnDivs=[];
		this.columnHuds=[];
		this.curColumn=0;

		for(i=0;i<colNum;i++) {
			div=this.columnDivs[i]=document.createElement('div');
			if(!beforeNode){
				box.columnDivs[i].appendChild(div);
			}else {
				box.columnDivs[i].insertBefore(div,beforeNode.columnDivs[i]);
			}
			div.style.width = "100%";
			div.style.position = "relative";
			div.style.left = "0px";
			div.style.top = "0px";
			div.style.height=box.rowH+"px";
			css=i?box.columnCSS[i-1](obj,this):box.nodeCSS(obj,this);
			if(css){
				this.webObj=div;
				this.curColumn=i;
				hud = JAXHudObj.createHudByType(css.type, this.jaxEnv, null, css, this);
				this.columnHuds[i]=hud;
				if(hud && hud.webObj){
					div.appendChild(hud.webObj);
				}
			}
		}
		this.curColumn=0;
	};

	JAXHudListNode.prototype = {};

	//---------------------------------------------------------------------------
	//用来创建Hud
	JAXHudListNode.prototype.appendChild = function (hud) {
		hud.father_ = this;
		hud.hold();
		if (hud.webObj) {
			this.webObj.appendChild(hud.webObj);
		}
	};

	//---------------------------------------------------------------------------
	//用来创建Hud
	JAXHudListNode.prototype.removeChild = function (hud) {
		if (hud.father_ !== this)
			return;
		if (hud.webObj) {
			this.webObj.removeChild(hud.webObj);
		}
		hud.release();
		hud.father_ = null;
	};

	//---------------------------------------------------------------------------
	//移除Box
	JAXHudListNode.prototype.freeNode = function () {
		var i,n,hud;
		var columns=this.columns;
		n=columns.length;
		for(i=0;i<n;i++){
			this.owner.columnDivs[i].removeChild(this.columnDivs[i]);
			hud=this.columnHuds[i];
			if(hud){
				hud.release();
				hud.owner_=null;
			}
		}
		this.columnDivs=null;
		this.columnHuds=null;
	};
}

//***************************************************************************
//树结构的Hud控件
//***************************************************************************
__Proto$3=new JAXHudObj();
JAXHudList=function(jaxEnv)
{
	var self;
	var nodeCSSFunc;
	var colCSSFunc;
	var selNodes;
	var hotNode;
	var columns;
	var multi;
	var nodeGap;
	var oldNodeGap;
	var headSpace,endSpace;
	var nodeList;
	var signUpdate;
	var _attrChanged;
	var rowH;

	self=this;
	JAXHudObj.call(this,jaxEnv);

	var valJXVMap,hudView;
	valJXVMap=this.$valJXVMap;
	hudView=this.hudView;

	this.clip=1;
	this.jaxClassFunc=JAXHudList;

	nodeCSSFunc=null;
	colCSSFunc=null;
	selNodes=new Set();
	hotNode=null;
	multi=0;
	rowH=30;
	nodeGap=0;
	oldNodeGap=0;
	headSpace=0;
	endSpace=50;
	this.nodeList_=nodeList=[];

	columns=this.columns=[];
	this.columnDivs=[];
	this.columnHeadDivs=[];
	this.columnEndDivs=[];

	signUpdate=this.signUpdate;

	_attrChanged=0;

	this.OnHotNodeChange=null;
	this.OnAddNode=null;
	this.OnInsertNode=null;
	this.OnSelNodeChange=null;
	this.OnFreeNode=null;
	this.OnMoveNode=null;


	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	Object.defineProperty(this,'columnDivs',{
		writable:false
	});

	var pxNodeList=new Proxy(nodeList,{
		get:function(obj,pName){
			switch(pName){
				case "indexOf":
					return obj.indexOf;
			}
			if(pName>=0 && pName<obj.length){
				return obj[pName];
			}else if(pName==='length'){
				return obj.length
			}
			return undefined;
		},
		set:function(obj,pName,v){}
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//---------------------------------------------------------------
		//行距:
		Object.defineProperty(this, 'rowH', {
			get: function () {
				return rowH;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('rowH');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('rowH');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'rowH', hudView);
						valJXVMap.set('rowH', v);
					}
					v=v.val;
				}
				if (v !== rowH) {
					rowH = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//顶部留白:
		Object.defineProperty(this, 'headSpace', {
			get: function () {
				return headSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('headSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('headSpace');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'headSpace', hudView);
						valJXVMap.set('headSpace', v);
					}
					v=v.val;
				}
				if (v !== headSpace) {
					headSpace = v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//底部留白:
		Object.defineProperty(this, 'endSpace', {
			get: function () {
				return endSpace;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('endSpace');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('endSpace');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'endSpace', hudView);
						valJXVMap.set('endSpace', v);
					}
					v=v.val;
				}
				if (v!==endSpace) {
					endSpace=v;
					_attrChanged = 1;
					signUpdate();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//允许多重选择:
		Object.defineProperty(this, 'multiSelect', {
			get: function () {
				return multi;
			},
			set: function (v) {
				if(v instanceof $JXV){
					let oldV;
					oldV = valJXVMap.get('intend');
					if (oldV) {
						oldV.untrace();
						valJXVMap.delete('intend');
					}
					if(v.traces!==0) {
						v.trace(this.$stateObj_, this, 'intend', hudView);
						valJXVMap.set('intend', v);
					}
					v=v.val;
				}
				if(v!==multi){
					multi=v;
					this.clearSelects();
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//子节点列表控件:
		Object.defineProperty(this,'nodes',{
			get:function(){
				return pxNodeList;
			},
			set:function(list){
				//这里什么都不干
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//生成子节点CSS的函数:
		Object.defineProperty(this,'nodeCSS',{
			get:function(){
				return nodeCSSFunc;
			},
			set:function(v){
				nodeCSSFunc=v;
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//生成子节点CSS的函数:
		Object.defineProperty(this,'columnCSS',{
			get:function(){
				return colCSSFunc;
			},
			set:function(v){
				if(!Array.isArray(v)){
					throw "Error: columnCSS is not array."
				}
				if(v.length<columns.length){
					throw "Error: columnCSS.length is not same with columns.length."
				}
				colCSSFunc=v;
			},
			configurable:true
		});

		//---------------------------------------------------------------
		//当前的焦点节点:
		Object.defineProperty(this, 'hotNode', {
			get: function () {
				return hotNode;
			},
			set: function (v) {
				if (v!==hotNode && v instanceof JAXHudListNode) {
					this.setHotNode(v);
				}
			},
			enumerable: true
		});

		//---------------------------------------------------------------
		//当前的选中节点列表:
		Object.defineProperty(this, 'selected', {
			get: function () {
				return selNodes;
			},
			set: function (v) {
			},
			enumerable: true
		});
	}

	//***********************************************************************
	//不会被继承的函数:
	//***********************************************************************
	{
		//---------------------------------------------------------------
		//删除全部滚动控件
		this.clear=this.removeAllNodes=function()
		{
			let list,i,n,node;
			if(hotNode){
				self.setHotNode(null);
			}
			selNodes.clear();
			list=nodeList;
			n=list.length;
			for(i=0;i<n;i++){
				node=list[i];
				node.freeNode();
			}
			list.splice(0);
		};

		//---------------------------------------------------------------
		//在指定节点下添加节点，如果指定节点不存在，则添加根节点
		this.addNode=function(obj)
		{
			let node;
			if(this.autoLayout){
				this._doLayout();
			}
			//添加根节点
			node = new JAXHudListNode(this,obj,null);
			nodeList.push(node);
			if (self.OnAddNode) {
				self.OnAddNode(obj,node);
			}
			return node;
		};

		//---------------------------------------------------------------
		//在指定节点下添加一组节点，如果指定节点不存在，则添加到根节点
		this.addNodes=function(list)
		{
			let node,obj,i,n;
			if(this.autoLayout){
				this._doLayout();
			}
			//添加根节点
			n=list.length;
			for(i=0;i<n;i++) {
				obj=list[i];
				node = new JAXHudListNode(this,obj,null);
				nodeList.push(node);
				if (self.OnAddNode) {
					self.OnAddNode(obj,node);
				}
			}
		};

		//---------------------------------------------------------------
		//在指定节点前插入节点
		this.insertNode=function(obj,beforeNode)
		{
			let node,idx;
			idx=nodeList.indexOf(beforeNode);
			if(idx<0) {
				return this.addNode(obj);
			}
			if(this.autoLayout){
				this._doLayout();
			}
			node = new JAXHudListNode(this,obj,beforeNode);
			nodeList.splice(idx,0,node);
			if (self.OnInsertNode) {
				self.OnInsertNode(idx,obj,node);
			}
			return node;
		};

		//---------------------------------------------------------------
		//在指定节点前插入多个节点
		this.insertNodes=function(list,beforeNode)
		{
			let i,n,obj,node,idx;
			idx = nodeList.indexOf(beforeNode);
			if (idx < 0) {
				return this.addNodes(list);
			}
			if(this.autoLayout){
				this._doLayout();
			}
			n=list.length;
			for(i=0;i<n;i++) {
				obj=list[i];
				node = new JAXHudListNode(this, obj, beforeNode);
				nodeList.splice(idx, 0, node);
				if (self.OnInsertNode) {
					self.OnInsertNode(idx,obj,node);
				}
				idx++;
			}
		};

		//---------------------------------------------------------------
		//删除节点
		this.removeNode=function(nodeNode)
		{
			var node,idx;
			node=nodeNode;
			idx=nodeList.indexOf(node);
			if(idx<0)
				return;
			if(node===hotNode){
				self.setHotNode(null);
			}
			selNodes.delete(nodeNode);
			nodeList.splice(idx,1);
			if(self.OnFreeNode){
				self.OnFreeNode(node);
			}
			node.freeNode();

		};

		//---------------------------------------------------------------
		//得到节点的序号:
		this.indexOfNode=function(node)
		{
			return nodeList.indexOf(node);
		};

		//---------------------------------------------------------------
		//得到节点的Hud控件:
		this.getNodeHud=function(node,column)
		{
			column=column?column:0;
			return node.columnHuds[column];
		};

		//---------------------------------------------------------------
		//得到Obj对应的节点:
		this.getNodeOfObj=function(obj)
		{
			let idx;
			let isNode = (node) => node.nodeObj===obj;
			idx=nodeList.findIndex(isNode);
			if(idx<0)
				return null;
			return nodeList[idx];
		};

		//---------------------------------------------------------------
		//设置当前高亮节点:
		this.setHotNode=function(nodeNode,addSel=0)
		{
			var node,hud;
			node=nodeNode;
			if(hotNode){
				if(selNodes.has(hotNode)){
					for(hud of hotNode.columnHuds){
						hud.face="selected";
					}
				}else {
					for(hud of hotNode.columnHuds){
						hud.face="normal";
					}
				}
			}
			hotNode=node;
			if(node) {
				if (multi && addSel) {
					selNodes.add(node);
				}else {
					this.clearSelects();
					selNodes.add(node);
				}
				for (hud of hotNode.columnHuds) {
					hud.face = "hot";
				}
			}else {
				if (!multi || !addSel) {
					this.clearSelects();
				}
			}
			if (this.OnHotNodeChange) {
				this.OnHotNodeChange(hotNode);
			}
		};

		//---------------------------------------------------------------
		//清除全部的选中节点
		this.clearSelects=function()
		{
			var node,hud;
			for(node of selNodes){
				for(hud of node.columnHuds){
					hud.face="normal";
				}
			}
			selNodes.clear();
			if(hotNode){
				hotNode.face="hot";
			}
			if(self.OnSelNodeChange){
				self.OnSelNodeChange();
			}
		};

		//---------------------------------------------------------------
		//选中节点
		this.selectNode=function(nodeNode)
		{
			var hud;
			selNodes.add(nodeNode);
			if(nodeNode!==hotNode){
				for(hud of nodeNode.columnHuds){
					hud.face="selected";
				}
				if(self.OnSelNodeChange){
					self.OnSelNodeChange();
				}
			}
		};

		//---------------------------------------------------------------
		//取消选中节点
		this.deselectNode=function(nodeNode)
		{
			var hud;
			selNodes.delete(nodeNode);
			if(nodeNode!==hotNode){
				for(hud of nodeNode.columnHuds){
					hud.face="normal";
				}
				if(self.OnSelNodeChange){
					self.OnSelNodeChange();
				}
			}
		};

		//TODO: 添加移动Node的方法:

		//---------------------------------------------------------------
		//找到一个节点
		this.findNode=function(func)
		{
			var node;
			for(node of nodeList){
				if(func(node)){
					return node;
				}
			}
			return null;
		};

		//---------------------------------------------------------------
		//获得节点的总数:
		this.getNodeNum=function(){
			return nodeList.length;
		};

		//---------------------------------------------------------------
		//获得一个节点的序号:
		this.indexOfNode=function(node){
			return nodeList.indexOf(node);
		};

		//-------------------------------------------------------------------
		//同步控件属性:
		this._syncWebObjAttr=function()
		{
			let webObj,list,i,n,node;
			webObj=this.webObj;
			if(!webObj) {
				return;
			}

			//TODO: 看看要不要逐列更新上下留白

			if(oldNodeGap!==nodeGap){
				list=nodeList;
				n=list.length;
				for(i=0;i<n;i++){
					node=list[i];
					node.webDiv.style.marginBottom=nodeGap+"px";
				}
				oldNodeGap=nodeGap;
			}
			_attrChanged=0;
		};

		//-------------------------------------------------------------------
		//在全部子节点（包含subs）里执行一个函数:
		this.execInTree=function(func){
			var list,i,n,hud;
			list=nodeList;
			n=list.length;
			for(i=0;i<n;i++){
				hud=list[i].hud;
				if(hud && func(hud)){
					return;
				}
			}
			list=this.chdHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				if(func(list[i])){
					return;
				}
			}
		};

		//---------------------------------------------------------------
		//当控件尺寸发生变化，调用这个函数
		this._sizeChanged=function(){
			let list,i,n,hud;
			list=nodeList;
			n=list.length;
			for(i=0;i<n;i++){
				hud=list[i].hud;
				if(hud.autoLayout){
					hud._doLayout();
				}
			}
			self.OnSizeChanged&&self.OnSizeChanged();
		};

	}
};

JAXHudList.prototype=__Proto$3;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudList.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
		'rowH','headSpace','endSpace','nodeCSS','columnCSS',
		'OnHotNodeChange','OnAddNode','OnInsertNode','OnSelNodeChange',
		'OnFreeNode','OnMoveNode','multiSelect'
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('list', function (env) {
		return new JAXHudList(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$3.preApplyCSS = function (cssObj)
	{
		var div, father, subDiv,i,n,columns,colDiv,offset;
		var headDiv,endDiv;
		let jaxEnv=this.jaxEnv;

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		this.removeAllChildren();
		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = cssObj.position||"absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;

			columns=this.columns=[0];
			if(cssObj.columns && Array.isArray(cssObj.columns)){
				columns=this.columns=columns.concat(cssObj.columns);
			}

			Object.defineProperty(this,'columns',{
				writable:false
			});

			//创建滚动框架div:
			subDiv=this.subHudDiv = document.createElement('div');
			div.appendChild(subDiv);
			subDiv.id="DIVListScroll";
			subDiv.style.position="absolute";
			subDiv.style.left="0px";
			subDiv.style.top="0px";
			subDiv.style.width="100%";
			subDiv.style.height="100%";
			subDiv.style.overflowY="scroll";
			subDiv.style.overflowX="hidden";

			//创建列对应的div:
			offset=0;
			n=columns.length;
			for(i=0;i<n;i++){
				colDiv=document.createElement('div');
				subDiv.appendChild(colDiv);
				colDiv.style.position="absolute";
				colDiv.style.left=offset+"px";
				colDiv.style.top="0px";
				colDiv.style.width=i?columns[i]+"px":"100%";
				colDiv.style.overflowX="hidden";
				colDiv.style.pointerEvents=i?"none":"";

				headDiv=document.createElement('div');
				headDiv.style.position="relative";
				headDiv.style.width="100%";
				colDiv.appendChild(headDiv);

				endDiv=document.createElement('div');
				endDiv.style.position="relative";
				endDiv.style.width="100%";
				colDiv.appendChild(endDiv);

				this.columnDivs[i]=colDiv;
				this.columnHeadDivs[i]=headDiv;
				this.columnEndDivs[i]=endDiv;
				offset+=columns[i];
			}
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		if(cssObj.jaxId){
			this["#self"]=this;
			//添加这个Hud
			jaxEnv.addHashObj("#"+cssObj.jaxId, this);
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS把pptList赋值后
	__Proto$3.finApplyCSS = function (cssObj)
	{
		if(this.webObj){
			this.webObj.id=this.id;
		}
		this.items2Add_=cssObj.items;
		this.nodes2Add_=cssObj.rows;
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$3.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		this.items2Add_=null;
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();
		list=this.nodes2Add_;
		if(Array.isArray(list)){
			this.addNodes(list,null);
		}
		delete this.nodes2Add_;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$3.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};
}

var JAXHudGroup,__Proto$2;

__Proto$2=new JAXHudObj();

JAXHudGroup=function(jaxEnv)
{
	var _attrChanged;

	JAXHudObj.call(this,jaxEnv);

	this.jaxClassFunc=JAXHudGroup;
	this.x=0;this.y=0;this.w=0;this.h=0;
	this.anchorV=0;this.anchorH=0;
	this.autoLayout=true;

	_attrChanged=0;

	Object.defineProperty(this,'attrChanged',{
		get:function(){return _attrChanged;},
		set:function(v){_attrChanged=1;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//控件宽度
		Object.defineProperty(this, 'w', {
			get: function () {
				return 0;
			},
			set: function (v) {
				return true;
			},
			enumerable: true,
			configurable:true
		});

		//控件高度
		Object.defineProperty(this, 'h', {
			get: function () {
				return 0;
			},
			set: function (v) {
				return true;
			},
			enumerable: true,
			configurable:true
		});

		//控件X锚点:
		Object.defineProperty(this, 'anchorH', {
			get: function () {
				return 0;
			},
			set: function (v) {
				return true;
			},
			enumerable: true,
			configurable:true
		});

		//控件Y锚点:
		Object.defineProperty(this, 'anchorV', {
			get: function () {
				return 0;
			},
			set: function (v) {
				return true;
			},
			enumerable: true,
			configurable:true
		});

		//控件客户区域宽度
		Object.defineProperty(this, 'clientW', {
			get: function () {
				let owner;
				owner=this.father_||this.owner_;
				return owner?owner.clientW:0;
			},
			set: function (v) {
				return v;
			},
			enumerable: true,
			configurable:true
		});

		//控件客户区域宽度
		Object.defineProperty(this, 'clientH', {
			get: function () {
				let owner;
				owner=this.father_||this.owner_;
				return owner?owner.clientH:0;
			},
			set: function (v) {
				return v;
			},
			enumerable: true,
			configurable:true
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		this._syncWebObjAttr=function(){
			_attrChanged=0;
		};
		
		this._doLayout=function(){
			let i,n,list,chd;
			list=this.chdHudList_;
			n=list.length;
			for(i=0;i<n;i++){
				chd=list[i];
				if(chd.autoLayout){
					chd._doLayout();
				}
			}
		};
		
	}
};

JAXHudGroup.prototype=__Proto$2;

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXHudGroup.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat([
	]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('group', function (env) {
		return new JAXHudGroup(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的开始，创建WebObj:
	__Proto$2.preApplyCSS = function (cssObj)
	{
		var div, father;
		let jaxEnv=this.jaxEnv;
		this.removeAllChildren();

		let owner,ownerState;
		father = this.father;
		owner = this.owner;

		if(!this.webObj) {
			div = this.webObj = document.createElement('div');
			div.style.position = "absolute";
			father = this.father;
			if (father && father.webObj) {
				father.webObj.appendChild(div);
			}
			div.jaxObj = this;
		}
		let style=cssObj.style;
		if(style){
			if(typeof(style)==="string") {
				div.style.cssText += style;
			}else {
				Object.assign(div.style,style);
			}
		}
		if(cssObj.faces){
			cssObj.jaxObjHash=1;
		}
		//确定StateObj:
		var stateObj=cssObj.hudState;
		if(stateObj){
			ownerState=father?father.stateObj:(owner?owner.stateObj:null);
			if(cssObj.jaxId){
				this["#self"]=this;
				//添加这个Hud
				jaxEnv.addHashObj("#"+cssObj.jaxId, this);
			}
			if(!stateObj.isJAXHudState) {
				stateObj = jaxHudState(this.jaxEnv, stateObj);
			}
			this.jaxEnv.pushHudState(stateObj);
			this.stateObj=stateObj;
			this.stateObj_=stateObj;
			stateObj.setupState(this,ownerState,this.hudView);
			if(cssObj.jaxId){
				//添加这个State对象
				jaxEnv.addHashObj("%"+cssObj.jaxId, stateObj);
			}
		}else {
			this.stateObj=this.jaxEnv.getCurHudState();
		}
	};

	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$2.postApplyCSS = function (cssObj)
	{
		let list;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}
		this._syncWebObj();
		this._holdAttr=false;
		this._syncWebObjAttr();

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
	};

	//---------------------------------------------------------------
	//更新控件内容
	__Proto$2.update=function()
	{
		let webObj;
		webObj=this.webObj;
		if(webObj) {
			if(this.attrChanged)
			{
				this._syncWebObjAttr();
			}
			//if(this.poseChanged)
			{
				this._syncWebObj();
			}
		}
	};
}

let JAXUIDock,__Proto$1;

JAXUIDock=function(jaxEnv){
	var self;
	var uiStack=[];
	var subUIs=[];
	var subHash={};
	var hideCovered=1;
	var dismissCovered=0;

	if(!jaxEnv){
		return;
	}
	self=this;
	JAXHudObj.call(this,jaxEnv);
	this.clip=1;

	this.OnRunoutUI=null;
	this.OnShowUI=null;
	this.OnUIShowed=null;
	this.OnCoverUI=null;
	this.OnUICovered=null;
	this.OnUncoverUI=null;
	this.OnUIUncovered=null;
	this.OnDismissUI=null;
	this.OnUIDismissed=null;

	//-----------------------------------------------------------------------
	//当前的UI:
	Object.defineProperty(this,'curUI',{
		get:function(){return uiStack[uiStack.length-1];},
		set:function(v){return v},
		enumerable:false
	});

	//-----------------------------------------------------------------------
	//当前的UI:
	Object.defineProperty(this,'dockUIs',{
		get:function(){return subUIs;},
		set:function(v){return subUIs;},
		enumerable:false
	});

	//***********************************************************************
	//CSS属性:
	//***********************************************************************
	{
		//-----------------------------------------------------------------------
		//当前的UI的Id，在subHash找到对应的UI进行显示:
		Object.defineProperty(this,'ui',{
			get:function(){
				var hud;
				hud=uiStack[uiStack.length-1];
				return hud;
			},
			set:function(v){
				var hud;
				hud=subUIs[v]||subHash[v];
				if(hud){
					self.showUI(hud,{});
				}
				return hud;
			},
			enumerable:true
		});

		//-----------------------------------------------------------------------
		//被遮挡的UI的处理:
		Object.defineProperty(this,'covered',{
			get:function(){
				switch(hideCovered){
					case 0:
						if(dismissCovered){
							return "dismiss";
						}
						return "stay";
					case 1:
						return "remove";
					case 2:
						return "hide";
				}
				return "";
			},
			set:function(v){
				switch(v){
					case "hide":
						hideCovered=2;
						dismissCovered=0;
						break;
					case "remove":
						hideCovered=1;
						dismissCovered=0;
						break;
					case "dismiss":
						hideCovered=0;
						dismissCovered=1;
						break;
					default:
						hideCovered=0;
						dismissCovered=0;
						break;
				}
				return v;
			},
			enumerable:true
		});
	}

	//***********************************************************************
	//不会被继承的方法:
	//***********************************************************************
	{
		//-------------------------------------------------------------------
		//用CSS添加一个新的UI
		this.showNewUI=function(cssVO,vo={},inSub=1){
			let uiId,preUI,result,ui;

			ui=this.appendNewChild(cssVO);
			if(!ui){
				return null;
			}
			preUI=this.curUI;
			if(preUI){
				preUI.uiEvent=0;
				this.OnCoverUI&&this.OnCoverUI(preUI,ui);
				if(preUI.coverUI) {
					preUI.coverUI();
				}
			}
			uiStack.push(ui);
			ui.uiEvent=0;
			result =ui.showUI?ui.showUI(vo,preUI):null;
			if(result instanceof Promise){
				result.then(()=>{
					this.OnShowUI&&this.OnShowUI(ui,preUI);
					ui.uiEvent=1;
					if(preUI) {
						this.OnUICovered&&this.OnUICovered(preUI);
						if(dismissCovered){
							self.dismissUI(preUI);
						}else if(hideCovered===1) {
							self.removeChild(preUI);
						}else if(hideCovered===2){
							preUI.display=0;
						}
						preUI.OnUICovered&&preUI.OnUICovered();
					}
					this.OnUIShowed&&this.OnUIShowed(ui);
				});
			}else {
				this.OnShowUI&&this.OnShowUI(ui,preUI);
				ui.uiEvent=1;
				if(preUI) {
					this.OnUICovered&&this.OnUICovered(preUI);
					if(dismissCovered) {
						self.dismissUI(preUI);
					}else if(hideCovered===1) {
						self.removeChild(preUI);
					}else if(hideCovered===2){
						preUI.display=0;
					}
					preUI.OnUICovered&&preUI.OnUICovered();
				}
				this.OnUIShowed&&this.OnUIShowed(ui);
			}
			ui.hold();
			if(inSub) {
				uiId = ui.id;
				if (uiId && !subHash[uiId]) {
					subUIs.push(ui);
					subHash[uiId] = ui;
				}
			}
			return ui;
		};

		//-------------------------------------------------------------------
		//显示UI:
		this.showUI=function(ui,vo){
			let idx,preUI,result;

			preUI=this.curUI;

			//同一个UI，调用showUI函数，不进行UI切换
			if(preUI===ui){
				result =ui.showUI?ui.showUI(vo,preUI):null;
				if(result instanceof Promise){
					result.then(()=>{
						this.OnUIShowed&&this.OnUIShowed(ui);
					});
				}else {
					this.OnUIShowed&&this.OnUIShowed(ui);
				}
				return ui;
			}

			if(typeof(ui)==="string"){
				ui=subHash[ui];
				if(!ui){
					jaxEnv.logError("JAXUIDock.showUI: UI has different father!");
					throw "JAXUIDock.showUI: UI has different father!";
				}
			}

			if(ui.father && ui.father!==this){
				jaxEnv.logError("JAXUIDock.showUI: UI has different father!");
				throw "JAXUIDock.showUI: UI has different father!";
			}
			idx=uiStack.indexOf(ui);
			if(idx>=0){
				uiStack.splice(idx,1);
			}
			uiStack.push(ui);
			if(!ui.father_) {
				this.appendChild(ui);
			}
			ui.display=1;
			if(preUI){
				preUI.uiEvent=0;
				this.OnCoverUI&&this.OnCoverUI(preUI,ui);
				if(preUI.coverUI) {
					preUI.coverUI();
				}
			}
			ui.uiEvent=0;
			result =ui.showUI?ui.showUI(vo,preUI):null;
			this.OnShowUI&&this.OnShowUI(ui,preUI);
			if(result instanceof Promise){
				result.then(()=>{
					ui.uiEvent=1;
					if(preUI) {
						preUI.OnUICovered&&preUI.OnUICovered();
						this.OnUICovered&&this.OnUICovered(preUI);
						if(dismissCovered) {
							self.dismissUI(preUI);
						}else if(hideCovered===1) {
							self.removeChild(preUI);
						}else if(hideCovered===2){
							preUI.display=0;
						}
						preUI.OnUICovered&&preUI.OnUICovered();
					}
					this.OnUIShowed&&this.OnUIShowed(ui);
				});
			}else {
				ui.uiEvent=1;
				if(preUI) {
					preUI.OnUICovered&&preUI.OnUICovered();
					this.OnUICovered&&this.OnUICovered(preUI);
					if(dismissCovered) {
						self.dismissUI(preUI);
					}else if(hideCovered===1) {
						self.removeChild(preUI);
					}else if(hideCovered===2){
						preUI.display=0;
					}
				}
				this.OnUIShowed&&this.OnUIShowed(ui);
			}
			return ui;
		};

		//-------------------------------------------------------------------
		//Remove a UI from dock for good:
		this.dismissUI=function(ui,remove=false){
			var topUI,nextUI,idx,result;
			topUI=self.curUI;
			if(!ui){
				ui=topUI;
			}
			if(ui!==topUI){
				//这个UI不是最上面的UI:
				idx=uiStack.indexOf(ui);
				if(idx>=0){
					uiStack.splice(idx,1);
				}
				this.OnDismissUI&&this.OnDismissUI(ui);
				if(ui.father===self){
					if(ui.dismissUI){
						result=ui.dismissUI();
						if(result instanceof Promise){
							result.then(()=>{
								this.OnUIDismissed&&this.OnUIDismissed();
								self.removeChild(ui);
								ui.release();
							});
						}
					}else {
						this.OnUIDismissed&&this.OnUIDismissed();
						self.removeChild(ui);
						ui.release();
					}
				}
			}else {
				//这个UI是最上面的UI:
				ui.uiEvent=0;
				uiStack.pop();//this.curUI will be the new top
				nextUI=this.curUI;
				if(nextUI){
					if(!nextUI.father_) {
						this.insertBefore(nextUI, ui);
					}
					nextUI.display=1;
					this.OnUncoverUI&&this.OnUncoverUI(nextUI);
					if(nextUI.showCovered){
						nextUI.showCovered();
					}
				}
				this.OnDismissUI&&this.OnDismissUI(ui);
				if(ui.dismissUI){
					result=ui.dismissUI();
					if(result instanceof Promise){
						result.then(()=>{
							this.OnUIDismissed&&this.OnUIDismissed();
							self.removeChild(ui);
							ui.release();
							if(nextUI){
								this.OnUIUncovered&&this.OnUIUncovered(nextUI);
								nextUI.uiEvent=1;
							}
						});
					}else {
						this.OnUIDismissed&&this.OnUIDismissed();
						self.removeChild(ui);
						ui.release();
						if(nextUI){
							this.OnUIUncovered&&this.OnUIUncovered(nextUI);
							nextUI.uiEvent=1;
						}
					}
				}else {
					this.OnUIDismissed&&this.OnUIDismissed();
					self.removeChild(ui);
					ui.release();
					if(nextUI){
						this.OnUIUncovered&&this.OnUIUncovered(nextUI);
						nextUI.uiEvent=1;
					}
				}
				if(!uiStack.length){
					this.OnRunoutUI&&this.OnRunoutUI();
				}
			}
		};

		//-------------------------------------------------------------------
		//增加一个被管理的UI:
		this.addDockUI=function(hud){
			if(subUIs.indexOf(hud)<0) {
				hud.hold();
				subUIs.push(hud);
				subHash[hud.id] = hud;
			}
		};
	}
};

__Proto$1=JAXUIDock.prototype=new JAXHudObj();

//***************************************************************************
//属性列表/注册创建函数:
//***************************************************************************
{
	//CSS属性列表
	JAXUIDock.jaxPptSet=new Set(Array.from(JAXHudObj.jaxPptSet).concat(["covered"]));

	//---------------------------------------------------------------------------
	//注册基础Hud类
	JAXHudObj.regHudByType('dock', function (env) {
		return new JAXUIDock(env);
	});
}

//***************************************************************************
//可继承的成员函数:
//***************************************************************************
{
	//---------------------------------------------------------------
	//ApplyCSS的最后，设置WebObj属性:
	__Proto$1.postApplyCSS = function (cssObj)
	{
		let list,uiId,uiType;
		list=this.items2Add_;
		if(Array.isArray(list)){
			this._applyItems(list);
		}
		delete this.items2Add_;

		//把子控件转换为管理的控件:
		{
			let hud;
			hud=this.firstChild;
			while(hud){
				this.addDockUI(hud);
				this.removeChild(hud);
				hud=this.firstChild;
			}
		}
		uiId=cssObj.ui;
		uiType=typeof(uiId);
		if(uiType==="number" && uiId>=0){
			this.showUI(this.dockUIs[uiId]);
		}else if(uiType==="string" && uiId){
			this.showUI(uiId,null);
		}else if(uiType==="object" && uiId){
			this.showNewUI(uiId);
		}
		if(cssObj.face){
			this.showFace(cssObj.face);
		}

		this._syncWebObj();
		this._holdAttr=false;

		let stateObj=this.stateObj_;
		if(stateObj){
			this.jaxEnv.popHudState(stateObj);
		}
	};

	//-----------------------------------------------------------------------
	//释放资源:
	__Proto$1.freeHud=function(){
		var father,div,list,i,n;
		list=this.dockUIs;
		n=list.length;
		for(i=0;i<n;i++){
			list[i].release();
		}
		list.splice(0);
		this.removeAllChildren();
		father=this.father;
		div=this.webObj;
		if(div && father && father.webObj){
			father=div.parentNode;
			if(father){
				father.removeChild(div);
			}
			this.webObj=null;
		}
	};
}

var diskVersion = {
	"coke": "0.0.11",
	"-jaxweb": "0.1.5",
	"-terminal": "0.1.09",
	"-diskit": "0.1.10",
	"-ccedit": "0.1.10",
	"-desktop": "0.1.8"
};

//Auto genterated by Cody
/*}#1FD92U5O70ExImports*/
//----------------------------------------------------------------------------
/*VO Object*/
var appCfg={
	"txtSize": {
		"small": 12, "smallMid": 14, "mid": 16, "midder": 18, "big": 20, "bigger": 24, "large": 28, "larger": 32, "huge": 40, "huger": 48, "shuge": 60
	},
	"size": {
		"btnNavi": 32, "userPhoto": 64, "naviBoxH": 50, "titleBoxH": 100, "btnStdH": 32
	},
	"color": {
		"btnStdFace": [30,100,180,1], "btnStdDown": [35,105,200,1], "btnStdGray": [200,200,200,1], "btnStdText": [255,255,255,1]
	},
	"shortCuts": {
	},
	/*#{1FD92U5O801*/
	workerVsnIdx:0,
	diskVsnIdx:{
		"jaxweb":1,
		"jaxext":0,
		"diskit":0,
		"ccedit":0,
		"desktop":0,
		"cody":0
	},
	diskVersion:diskVersion
	/*}#1FD92U5O801*/
};
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"name": "appCfg.js", "type": "object", "def": "CdyFileAppCfg", "jaxId": "1FD92U5O70", 
//			"attrs": {
//				"appCfg": {
//					"name": "appCfg", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FD92U5O80", 
//					"attrs": {
//						"txtSize": {
//							"name": "txtSize", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FD953NKI0", 
//							"attrs": {
//								"small": {"type":"int","valText":"12","initVal":"","info":null,"tip":null}, 
//								"smallMid": {"type":"int","valText":"14","initVal":"","info":null,"tip":null}, 
//								"mid": {"type":"int","valText":"16","initVal":"","info":null,"tip":null}, 
//								"midder": {"type":"int","valText":"18","initVal":"","info":null,"tip":null}, 
//								"big": {"type":"int","valText":"20","initVal":"","info":null,"tip":null}, 
//								"bigger": {"type":"int","valText":"24","initVal":"","info":null,"tip":null}, 
//								"large": {"type":"int","valText":"28","initVal":"","info":null,"tip":null}, 
//								"larger": {"type":"int","valText":"32","initVal":"","info":null,"tip":null}, 
//								"huge": {"type":"int","valText":"40","initVal":"","info":null,"tip":null}, 
//								"huger": {"type":"int","valText":"48","initVal":"","info":null,"tip":null}, 
//								"shuge": {"type":"int","valText":"60","initVal":"","info":null,"tip":null}
//							}
//						}, 
//						"size": {
//							"name": "size", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FD953NKI1", 
//							"attrs": {
//								"btnNavi": {"type":"int","valText":"32","initVal":"","info":null,"tip":null}, 
//								"userPhoto": {"type":"int","valText":"64","initVal":"","info":null,"tip":null}, 
//								"naviBoxH": {"type":"int","valText":"50","initVal":"","info":null,"tip":null}, 
//								"titleBoxH": {"type":"int","valText":"100","initVal":"","info":null,"tip":null}, 
//								"btnStdH": {"type":"int","valText":"32","initVal":"","info":null,"tip":null}
//							}
//						}, 
//						"color": {
//							"name": "color", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAF6F8J0", 
//							"attrs": {
//								"btnStdFace": {
//									"type": "colorRGBA", "valText": "[30,100,180,1]", "initVal": "", 
//									"info": null, "tip": null
//								}, 
//								"btnStdDown": {
//									"type": "colorRGBA", "valText": "[35,105,200,1]", "initVal": "", 
//									"info": null, "tip": null
//								}, 
//								"btnStdGray": {
//									"type": "colorRGBA", "valText": "[200,200,200,1]", "initVal": "", 
//									"info": null, "tip": null
//								}, 
//								"btnStdText": {
//									"type": "colorRGBA", "valText": "[255,255,255,1]", "initVal": "", 
//									"info": null, "tip": null
//								}
//							}
//						}, 
//						"shortCuts": {
//							"name": "shortCuts", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBPCR1F0", 
//							"attrs": {}
//						}
//					}
//				}
//			}
//		}/*Doc}#*/;
//	}

//Auto genterated by Cody
/*App的多语言文本库文件*/
//----------------------------------------------------------------------------
/*Object for text lib*/
var textLib={
	EN:
	{
	},
	CN:
	{
	}

};
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"jaxId": "1FD92U5O90", "def": "CdyFileTextLib", 
//			"attrs": {
//				"EN": {
//					"name": "EN", "type": "object", "def": "CdyLanguage", "jaxId": "1FD92U5O91", 
//					"attrs": {}
//				}, 
//				"CN": {
//					"name": "CN", "type": "object", "def": "CdyLanguage", "jaxId": "1FD92U5O92", 
//					"attrs": {}
//				}
//			}, 
//			"textLib": {
//				"name": "textLib", "type": "object", "def": "CdyTextLib", "jaxId": "1FD92U5O93", 
//				"attrs": {}
//			}
//		}/*Doc}#*/;
//	}

//Auto genterated by Cody
/*App的总数据文件*/
/*#{1FD92U5OB0Imports*/
/*}#1FD92U5OB0Imports*/

//----------------------------------------------------------------------------
/*App的入口文件*/
var appData={};

//App数据初始化函数:
appData.initData=function(jaxEnv){
	/*#{1FD92U5OB0initPre*/
	/*}#1FD92U5OB0initPre*/
	this.jaxEnv=jaxEnv;
	this.version="0.0.0";
	/*#{1FD92U5OB0initPost*/
	/*}#1FD92U5OB0initPost*/
};
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"jaxId": "1FD92U5OB0", "dataObj": {"version":"\"0.0.0\""}, 
//			"funcs": {"jaxId":"1FD92U5OB1","funcs":[]}
//		}/*Doc}#*/;
//	}

//Auto genterated by Cody
/*}#1FD9CKN510Imports*/
/*DataClass*/
var CCFile, CCFolder, CCDisk;
let __Proto;

//*****************************************************
/*CCFile: Data object class*/
//*****************************************************
{
	CCFile=function(appData, disk, item){
		/*#{1FD9E38RQ0Pre*/
		/*}#1FD9E38RQ0Pre*/
		if(!appData){return;}
		JAXDataObj.call(this,appData.jaxEnv);
		this.appData=appData;
		
		//Data attributes:
		this.type = "file";
		this.isFolder = 0;
		this.path = "";
		this.name = "";
		this.baseVersion = 0;
		this.modified = 0;
		this.size = 0;
		this.modifiedTime = 0;
		/*#{1FD9E38RQ0Post*/
		/*}#1FD9E38RQ0Post*/
	};
	__Proto=CCFile.prototype={};
	
	
	/*#{1FD9E38RQ0Functions*/
	/*}#1FD9E38RQ0Functions*/
}
//*****************************************************
/*CCFolder: Data object class*/
//*****************************************************
{
	CCFolder=function(appData, disk, item){
		/*#{1FD9E326S0Pre*/
		/*}#1FD9E326S0Pre*/
		if(!appData){return;}
		JAXDataObj.call(this,appData.jaxEnv);
		this.appData=appData;
		
		//Data attributes:
		this.type = "folder";
		this.isFolder = 1;
		this.name = "";
		this.baseVersion = 0;
		this.modified = 0;
		this.modifiedTime = 0;
		/*#{1FD9E326S0Post*/
		this.folderItem=item;
		this.disk=disk;
		this.name=item.name;
		this.path=item.path;
		this.diskPath=item.diskPath;
		this.modified=item.modified?1:0;
		this.modifiedTime=item.modifiedTime||0;
		/*}#1FD9E326S0Post*/
	};
	__Proto=CCFolder.prototype={};
	
	
	/*#{1FD9E326S0Functions*/
	//------------------------------------------------------------------------
	//得到目录下的项目列表
	__Proto.getSubItems=function(fileSet){
		/*#{1FBS4TI4Q0Code*/
		return this.disk.getSubItems(this.path,fileSet?fileSet:null);
		/*}#1FBS4TI4Q0Code*/
	};
	
	//------------------------------------------------------------------------
	//得到目录下的目录列表
	__Proto.getSubFolders=function(){
		/*#{1FBTKC9RB0Code*/
		return this.disk.getSubFolders(this.path);
		/*}#1FBTKC9RB0Code*/
	};
	/*}#1FD9E326S0Functions*/
}
//*****************************************************
/*CCDisk: Data object class*/
//*****************************************************
{
	CCDisk=function(appData, diskObj, diskName){
		/*#{1FD9DNECB0Pre*/
		/*}#1FD9DNECB0Pre*/
		if(!appData){return;}
		JAXDataObj.call(this,appData.jaxEnv);
		this.appData=appData;
		
		//Data attributes:
		this.type = "disk";
		this.name = diskName;
		this.diskId = "";
		this.baseVersion = 0;
		this.modified = 0;
		this.modifiedTime = 0;
		/*#{1FD9DNECB0Post*/
		this.diskObj=diskObj;
		this.path="";
		this.diskPath=diskName;
		/*}#1FD9DNECB0Post*/
	};
	__Proto=CCDisk.prototype={};
	
	
	/*#{1FD9DNECB0Functions*/
	//------------------------------------------------------------------------
	//Get all folders (CCFolder obj) under [path]
	__Proto.getSubFolders=function(path){
		/*#{1FBTJMJG80Code*/
		let disk=this.diskObj;
		path=path?path:"";
		return disk.getEntries(path).then(list => {
			var dirList=[],item;
			for(item of list){
				item.disk=disk;
				item.path=path?(path+"/"+item.name):item.name;
				item.diskPath=disk.name+":"+item.path;
				if(item.dir){
					dirList.push(new CCFolder(app.appData,this,item));
				}
			}
			dirList.sort((v1,v2)=>{
				return v1.name>v2.name?1:(v1.name<v2.name?-1:0)
			});
			return dirList;
		});
		/*}#1FBTJMJG80Code*/
	};
	
	//------------------------------------------------------------------------
	//Get item entries under [path], CCFolder for folder, CCFile for file;
	__Proto.getSubItems=function(path, fileSet){
		/*#{1FBS4QOIB3Code*/
		let disk=this.diskObj;
		//处理单参数fileSet:
		if(path instanceof Set){
			fileSet=path;
			path="";
		}
		path=path?path:"";
		return disk.getEntries(path).then(list => {
			var dirList=[],item;
			for(item of list){
				if(fileSet && !fileSet.has(item.name)){
					continue;
				}
				item.disk=disk;
				item.path=path?(path+"/"+item.name):item.name;
				item.diskPath=disk.name+":"+item.path;
				if(item.dir){
					dirList.push(new CCFolder(app.appData,this,item));
				}else {
					dirList.push(new CCFile(app.appData,this,item));
				}
			}
			dirList.sort((v1,v2)=>{
				if(v1.isFolder && !v2.isFolder) return -1;
				if(!v1.isFolder && v2.isFolder) return 1;
				return v1.name>v2.name?1:(v1.name<v2.name?-1:0)
			});
			return dirList;
		});
		/*}#1FBS4QOIB3Code*/
	};
	
	var diskMap={};
	var app=null;
	
	//------------------------------------------------------------------------
	//Init CCDisk system.
	CCDisk.init=function(app_){
		if(app){
			throw "Disk system is already inited!";
		}
		app=app_;
		return JAXDisk.init();
	};
	
	//------------------------------------------------------------------------
	//Get current disks' name list:
	CCDisk.getDiskList=function(){
		return new Promise((resolve, reject) => {
			var disks,name,list=[];
			disks=JAXDisk.getDisks();
			for(name of disks){
				list.push(name);
			}
			resolve(list);
		});
	};
	
	//------------------------------------------------------------------------
	//Get a disk CCDisk obj by [name]
	CCDisk.getDisk=function(name){
		let disk;
		disk=diskMap[name];
		if(disk){
			return new Promise((resolve,reject)=>{resolve(disk);});
		}
		return JAXDisk.openDisk(name,0).then(diskObj=>{
			if(diskObj) {
				disk=new CCDisk(app.appData,diskObj,name);
				diskMap[name] = disk;
			}
			return disk;
		});
	};
	
	//------------------------------------------------------------------------
	//Add a foler by [path]
	__Proto.addNewFolder=function(path,name){
		let disk=this.diskObj;
		let self=this;
		if(!name){
			name=JAXEnv.getFileName(path);
		}
		return disk.isExist(path).then(exist=>{
			if(exist){
				throw("Path is already existed!");
			}
			return disk.newDir(path).then(obj=>{
				var time;
				time=Date.now();
				if(obj){
					obj={};
					obj.name=name;
					obj.disk=self;
					obj.path=path;
					obj.diskPath=self.name+":"+path;
					obj.createTime=time;
					obj.modifyTime=time;
					return new CCFolder(app.appData,self,obj);
				}
				throw("Add new folder error.");
			});
		});
	};
	
	//------------------------------------------------------------------------
	//Check a set of files/dirs ([pathes]) if they are exists, return a array that includes all item path that exist.
	__Proto.checkFilesExist=function(pathes){
		let disk,pList,eList,i,n;
		
		function checkOne(path){
			return disk.isExist(path).then(exist=>{
				if(exist){
					eList.push(path);
				}
			});
		}
		
		disk=this.diskObj;
		pList=[];eList=[];
		n=pathes.length;
		for(i=0;i<n;i++){
			pList.push(checkOne(pathes[i]));
		}
		return Promise.all(pList).then(()=>{
			return eList
		});
	};

	//------------------------------------------------------------------------
	//Save a [file] to [path]
	__Proto.uploadOneFile=function(path,file,overwrite=1){
		let disk;
		disk=this.diskObj;
		if(overwrite){
			return this.diskObj.saveFile(path,file);
		}else {
			return disk.isExist(path).then(exist=>{
				if(!exist){
					return this.diskObj.saveFile(path,file);
				}
				return;
			});
		}
	};
	
	//------------------------------------------------------------------------
	//Delete files
	__Proto.delItems=function(files){
		let pList,disk,i,n,path;
		disk=this.diskObj;
		pList=[];
		n=files.length;
		for(i=0;i<n;i++){
			path=files[i];
			pList.push(disk.del(path));
		}
		return Promise.allSettled(pList);
	};
	
	//------------------------------------------------------------------------
	//Make zip from [path]
	__Proto.makeZip=async function (path,items) {
		var disk,zipFile;

		disk=this.diskObj;
		async function zipDir(dirPath,zipPath,list){
			let i,n,stub;
			zipFile.folder(zipPath);
			if(!list){
				list=await disk.getEntries(dirPath);
			}
			n=list.length;
			for(i=0;i<n;i++){
				stub=list[i];
				if(stub.dir){
					await zipDir(JAXEnv.genFilePath(dirPath,stub.name),JAXEnv.genFilePath(zipPath,stub.name));
				}else {
					let fileData;
					fileData=await disk.loadFile(JAXEnv.genFilePath(dirPath,stub.name));
					if(fileData) {
						zipFile.file(JAXEnv.genFilePath(zipPath, stub.name), fileData);
					}
				}
			}
		}

		zipFile=new JSZip();
		return zipDir(path,"",items).then(()=>{
			return zipFile.generateAsync({type : "uint8array"});
		});
	};
	
	//------------------------------------------------------------------------
	//Extract [zipFile] to basePath:
	__Proto.extractZip=async function(basePath,zipFile,dirZipName=0,logger=null){
		var zipDir,zipDirs,zipName,disk;
		disk=this.diskObj;
		zipDirs=[];
		zipName=zipFile.name;
		if(zipName){
			let pos;
			pos=zipName.lastIndexOf(".");
			if(pos>0){
				zipName=zipName.substring(0,pos);
			}
		}
		if(zipName && dirZipName){
			zipDir=basePath+(basePath?"/":"")+zipName;
		}else {
			zipDir=basePath;
		}

		async function doFiles(list){
			let filePath,i,n,path,zipObj;
			n=list.length;
			for(i=0;i<n;i++){
				path=list[i].path;
				zipObj=list[i].zipObj;
				filePath=JAXEnv.genFilePath(zipDir,path);
				await zipObj.async("uint8array").then((buf)=>{
					if(logger){
						logger.state("Extracting file: "+filePath);
					}else {
						console.log("Extracting file: "+filePath);
					}
					return disk.saveFile(filePath,buf,false);
				});
			}
			return true;
		}

		async function doDirs(list){
			let i,n,path;
			n=list.length;
			for(i=0;i<n;i++){
				path=list[i];
				await disk.newDir(path);
			}
			return true;
		}
		
		if(logger){
			logger.log("Start extracting zip...");
		}
		return zipFile.arrayBuffer().then(buf=>{
			return JSZip.loadAsync(buf).then(async zip=>{
				let list=[];
				zip.forEach((path,zipObj)=>{
					console.log("File in zip: "+path);
					if(zipObj.dir){
						let dirPath;
						dirPath=JAXEnv.genFilePath(zipDir,path);
						zipDirs.push(dirPath);
					}else {
						list.push({path:path,zipObj:zipObj});
					}
				});
				await doDirs(zipDirs);
				await doFiles(list);
			});
		});
	};
	
	//------------------------------------------------------------------------
	//Extract Zip fast:
	__Proto.extractZipFast=async function(tgtPath,zipFile,logger=null){
		let dirEntries={};
		let pmsList=[];
		let disk,diskName,zipDir,pms,zipDirObj,dirPrefix;
		
		async function parseTgtPath(){
			if(tgtPath.endsWith("/")){
				tgtPath=tgtPath.substring(tgtPath.length-1);
			}
			if(!tgtPath.startsWith("/")){
				throw Error(`Zip path ${tgtPath} is not full-path`);
			}
			let pos=tgtPath.indexOf("/",1);
			if(pos>0) {
				diskName = tgtPath.substring(1, pos);
				zipDir = tgtPath.substring(pos + 1);
				dirPrefix=zipDir+"/";
			}else {
				diskName = tgtPath.substring(1);
				zipDir = "";
				dirPrefix="";
			}
			disk = await JAXDisk.openDisk(diskName, true);
			zipDirObj=await get$1(zipDir||".",disk.dbStore);
			dirEntries[""]=zipDirObj;
		}
		function parsePath(path){
			let pos=path.lastIndexOf("/");
			if(pos>0){
				return [path.substring(0,pos),path.substring(pos+1)];
			}
			return ["",path];
		}
		function getDir(dir){
			let entry;
			entry=dirEntries[dir];
			if(!entry){
				entry={};
				dirEntries[dir]=entry;
				if(dir) {
					let [dirname, basename] = parsePath(dir);
					let upperEntry = getDir(dirname);
					let time = Date.now();
					upperEntry[basename] = { name: basename, dir: 1, createTime: time, modifyTime: time };
				}
			}
			return entry;
		}
		async function digestBytes(buf) {
			let hex;
			const hashBuffer = await crypto.subtle.digest('SHA-256', buf);     // hash the data
			const hashArray = Array.from(new Uint8Array(hashBuffer));          // convert buffer to byte array
			hex= hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
			return hex;
		}
		function writeFile(path,data){
			let [dirname,basename]=parsePath(path);
			let dirEntry=getDir(dirname);
			let time=Date.now();
			return digestBytes(data).then(byteHex=>{
				dirEntry[basename]={name:basename,dir:0,createTime:time,modifyTime:time,size:data.byteLength,modified:true,
						hash:byteHex};
				return set$1(dirPrefix+path,data,disk.dbStore);
			});
		}
		
		let zipBuf=await zipFile.arrayBuffer();
		let zip=await JSZip.loadAsync(zipBuf);
		let fileList=[];
		
		await parseTgtPath();
		
		//disk=await JAXDisk.openDisk(diskName,true);
		zip.forEach(async (path,zipObj)=>{
			if(zipObj.dir){
				if(path.endsWith("/")){
					path=path.substring(0,path.length-1);
				}
				getDir(path);
			}else {
				fileList.push({path:path,zipObj:zipObj});
				//let buf=await zipObj.async("uint8array");
				//pms=writeFile(path,buf);
				/*pms=zipObj.async("uint8array").then((buf)=>{
					return writeFile(path,buf);
				});*/
				//pmsList.push(pms);
			}
		});
		async function unpackFile(stub){
			let filePath=stub.path;
			let zipObj=stub.zipObj;
			let buf;
			buf=await zipObj.async("uint8array");
			if(logger){
				logger.state("Extracting file: "+filePath);
			}else {
				console.log("Extracting file: "+filePath);
			}
			pms=writeFile(filePath,buf).then(()=>{
				if(logger){
					logger.state("Extracted file: "+filePath);
				}else {
					console.log("Extracted file: "+filePath);
				}
			});
			pmsList.push(pms);
		}
		for(let i=0,n=fileList.length;i<n;i++){
			await unpackFile(fileList[i]);
		}
		await Promise.all(pmsList);//Wait all file write into disk
		pmsList.splice(0);
		let dirPath,dirEntry;
		dirEntry=dirEntries[""];
		delete dirEntries[""];
		if(zipDir){
			pms=set$1(zipDir,dirEntry,disk.dbStore);
			pmsList.push(pms);
		}else {
			pms=set$1(".",dirEntry,disk.dbStore);
			pmsList.push(pms);
		}
		let dirKeys=Object.keys(dirEntries);
		for(let i=0,n=dirKeys.length;i<n;i++){
			dirPath=dirKeys[i];
			dirEntry=dirEntries[dirPath];
			pms=set$1(dirPrefix+dirPath,dirEntry,disk.dbStore);
			pmsList.push(pms);
		}
		return Promise.all(pmsList);
	};
	
	//------------------------------------------------------------------------
	//Download zip from URL, extract to disk by [diskName]
	__Proto.fetchDisk=async function(zipURL,diskName,logger){
		let self=this;
		logger.log("Will fetch file: "+zipURL);
		logger.state("Fetching file: "+zipURL);
		return fetch(zipURL).then(res=>{
			if(res.ok){
				logger.log("dowloading file: "+zipURL);
				
				return self.extractZipFast("/"+this.name,res,logger);
				
				/*return self.extractZip("",res,0,logger).then(()=>{
					logger.log("Disk file: "+zipURL+" extracted.");
				});*/
			}else {
				logger.log("Fetch file "+zipURL+" failed: "+res.status+": "+res.statusText);
				throw "Fecth failed";
			}
		});
	};
	
	//------------------------------------------------------------------------
	//Install a disk from zipURL.
	CCDisk.installDisk=async function(zipURL,diskName,logger,deleteOld=1){
		let disk;
		//Open current disk:
		disk=await JAXDisk.openDisk(diskName,0);
		if(disk && deleteOld){
			//Delete current disk:
			await JAXDisk.dropDisk(diskName);
		}
		disk=await JAXDisk.openDisk(diskName,1);
		disk=new CCDisk(app.appData,disk,diskName);
		await JAXDisk.setDiskAttr(diskName,"diskType","System");
		return disk.fetchDisk(zipURL,diskName,logger);
	};
	/*}#1FD9DNECB0Functions*/
}
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"jaxId": "1FD9CKN510", "def": "CdyFileDataClass", 
//			"attrs": {"fileName":"\"CCDisk\"","description":"\"\""}, 
//			"classObjs": {
//				"name": "classObjs", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9CKN511", 
//				"attrs": {
//					"CCFile": {
//						"type": "object", "def": "CdyDataClass", "name": "CCFile", "tip": "", "jaxId": "1FD9E38RQ0", 
//						"attrs": {}, 
//						"args": {
//							"name": "Arguments", "type": "object", "def": "ClassObjArgObj", "jaxId": "1FD9E83GE0", 
//							"attrs": {
//								"superClass": "\"JAXDataObj\"", 
//								"disk": {"type":"auto","valText":"null","info":null,"tip":null}, 
//								"item": {"type":"auto","valText":"null","info":null,"tip":null}
//							}
//						}, 
//						"pptsObj": {
//							"name": "Properties", "type": "object", "def": "ClassObjPptObj", "jaxId": "1FD9E83GE1", 
//							"attrs": {
//								"type": {
//									"type": "string", "valText": "\"file\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"isFolder": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"path": {
//									"type": "string", "valText": "\"\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"name": {
//									"type": "string", "valText": "\"\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"baseVersion": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modified": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"size": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modifiedTime": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}
//							}
//						}, 
//						"funcsObj": {"jaxId":"1FD9E83GE2","funcs":[]}, 
//						"mockObjs": {
//							"name": "Mockups", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9E83GE3", 
//							"attrs": {}
//						}
//					}, 
//					"CCFolder": {
//						"type": "object", "def": "CdyDataClass", "name": "CCFolder", "tip": "", "jaxId": "1FD9E326S0", 
//						"attrs": {}, 
//						"args": {
//							"name": "Arguments", "type": "object", "def": "ClassObjArgObj", "jaxId": "1FD9E83GE4", 
//							"attrs": {
//								"superClass": "\"JAXDataObj\"", 
//								"disk": {"type":"auto","valText":"null","info":null,"tip":null}, 
//								"item": {"type":"auto","valText":"null","info":null,"tip":null}
//							}
//						}, 
//						"pptsObj": {
//							"name": "Properties", "type": "object", "def": "ClassObjPptObj", "jaxId": "1FD9E83GE5", 
//							"attrs": {
//								"type": {
//									"type": "string", "valText": "\"folder\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"isFolder": {"type":"int","valText":"1","initVal":"","info":null,"tip":null}, 
//								"name": {
//									"type": "string", "valText": "\"\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"baseVersion": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modified": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modifiedTime": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}
//							}
//						}, 
//						"funcsObj": {"jaxId":"1FD9E83GE6","funcs":[]}, 
//						"mockObjs": {
//							"name": "Mockups", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9E83GE7", 
//							"attrs": {}
//						}
//					}, 
//					"CCDisk": {
//						"type": "object", "def": "CdyDataClass", "name": "CCDisk", "tip": "", "jaxId": "1FD9DNECB0", 
//						"attrs": {}, 
//						"args": {
//							"name": "Arguments", "type": "object", "def": "ClassObjArgObj", "jaxId": "1FD9DSUG50", 
//							"attrs": {
//								"superClass": "\"JAXDataObj\"", 
//								"diskObj": {"type":"auto","valText":"null","info":null,"tip":null}, 
//								"diskName": {
//									"type": "string", "valText": "\"\"", "initVal": "", "info": null, 
//									"tip": null
//								}
//							}
//						}, 
//						"pptsObj": {
//							"name": "Properties", "type": "object", "def": "ClassObjPptObj", "jaxId": "1FD9DSUG51", 
//							"attrs": {
//								"type": {
//									"type": "string", "valText": "\"disk\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"name": {
//									"type": "string", "valText": "#diskName", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"diskId": {
//									"type": "string", "valText": "\"\"", "initVal": "", "info": null, 
//									"tip": null
//								}, 
//								"baseVersion": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modified": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}, 
//								"modifiedTime": {"type":"int","valText":"0","initVal":"","info":null,"tip":null}
//							}
//						}, 
//						"funcsObj": {"jaxId":"1FD9DSUG52","funcs":[]}, 
//						"mockObjs": {
//							"name": "Mockups", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9DSUG53", 
//							"attrs": {}
//						}
//					}
//				}
//			}
//		}/*Doc}#*/;
//	}

class Store {
	constructor(dbName = 'keyval-store', storeName = 'keyval') {
		this.storeName = storeName;
		this._dbp = new Promise((resolve, reject) => {
			const openreq = indexedDB.open(dbName, 1);
			openreq.onerror = () => reject(openreq.error);
			openreq.onsuccess = () => resolve(openreq.result);
			// First time setup: create an empty object store
			openreq.onupgradeneeded = () => {
				openreq.result.createObjectStore(storeName);
			};
		});
	}
	_withIDBStore(type, callback) {
		return this._dbp.then(db => new Promise((resolve, reject) => {
			const transaction = db.transaction(this.storeName, type);
			transaction.oncomplete = () => resolve();
			transaction.onabort = transaction.onerror = () => reject(transaction.error);
			callback(transaction.objectStore(this.storeName));
		}));
	}
}
let store;
function getDefaultStore() {
	if (!store)
		store = new Store();
	return store;
}
function get(key, store = getDefaultStore()) {
	let req;
	return store._withIDBStore('readonly', store => {
		req = store.get(key);
	}).then(() => req.result);
}
function set(key, value, store = getDefaultStore()) {
	return store._withIDBStore('readwrite', store => {
		store.put(value, key);
	});
}

//This file is based on https://github.com/alphaeadevelopment/parse-version-string.git

/*
In coke, disk verison is must be like: [major.minor.patch].
Package version can be extended like [major.minor.path-tag.versionIdx].
*/

const pattern = /([0-9]+)\.([0-9]+)\.([0-9]+)(-(([a-z]+)([.-]([0-9]+))?)?)?/;

let Version=function(version){
	if (!version){
		return null;
	}

	let match = version.match(pattern);
	if (!match){
		return null;
	}

	let rv = {
		major: Number(match[1]),
		minor: Number(match[2]),
		patch: Number(match[3]),
	};
	if (match[5]) {
		rv.tag=match[6];
		rv.versionIdx=Number(match[8]);
	}
	return rv;
};

//----------------------------------------------------------------------------
//Check if text is valid version string
Version.valid=function(text){
	return !!Version(text);
};

//----------------------------------------------------------------------------
//Clean text to pure version-string.
Version.valid=function(text){
	let v=Version(text);
	if(!v){
		return null;
	}
	return `${v.major}.${v.minor}.${v.patch}`;
};

//----------------------------------------------------------------------------
//Compare two version
let compare=Version.compare=function(v1,v2)
{
	if(!v1 || !v2){
		return NaN;
	}
	if(v1.major>v2.major){
		return 1;
	}else if(v1.major<v2.major){
		return -1;
	}else if(v1.minor>v2.minor){
		return 1;
	}else if(v1.minor<v2.minor){
		return -1
	}else if(v1.patch>v2.patch){
		return 1;
	}else if(v1.patch<v2.patch){
		return -1;
	}else {
		return 0;
	}
};

//----------------------------------------------------------------------------
//Compare two version
Version.compareR=function(v1,v2)
{
	return compare(v2,v1);
};

//----------------------------------------------------------------------------
//Compare two version-text
Version.compareText=function(text1,text2)
{
	let v1,v2;
	v1=Version(text1);
	v2=Version(text2);
	return compare(v1,v2);
};

//----------------------------------------------------------------------------
//Compare two version-text
Version.compareTextR=function(text1,text2){
	return Version.compareText(text2,text1);
};

let version=Version;

//Auto genterated by Cody
/*}#1FD9FKBJE0Imports*/
/*DataClass*/
var CCWorker;

//*****************************************************
/*CCWorker: Data object class*/
//*****************************************************
{
	CCWorker=function(appData){
		/*#{1FD9FKIR00Pre*/
		/*}#1FD9FKIR00Pre*/
		if(!appData){return;}
		JAXDataObj.call(this,appData.jaxEnv);
		this.appData=appData;
		
		//Data attributes:
		/*#{1FD9FKIR00Post*/
		/*}#1FD9FKIR00Post*/
	};
	CCWorker.prototype={};
	
	
	/*#{1FD9FKIR00Functions*/
	//------------------------------------------------------------------------
	//检查当前是否正确安装了ServiceWorker:
	CCWorker.checkWorker=async function(){
		let reg,store,scope,version;
		version=appCfg.workerVsnIdx;
		scope="/";
		reg=await navigator.serviceWorker.getRegistration(scope);
		if(!reg){
			return false;
		}
		if(version>0){
			store = new Store('JAXSys', "ServiceWorker");
			return get("version", store).then(ver=>{
				return ver>version;
			});
		}
		return true;
	};
	
	//------------------------------------------------------------------------
	//检查当前的工具磁盘:
	CCWorker.checkLibs=async function(){
		let text,vo;
		let libs={};
		async function checkDisk(diskName,pkgName){
			let disk;
			pkgName=pkgName||diskName;
			disk=await JAXDisk.openDisk(diskName);
			if(disk){
				text=await disk.loadText("disk.json");
				try{
					vo=JSON.parse(text);
					libs[pkgName]=vo;
					if(appCfg.diskVersion[diskName]){
						vo.checked=version.compareText(vo.version,appCfg.diskVersion[diskName])>=0;
					}else {
						vo.checked=false;
					}
				}catch(e){
					libs[pkgName]=null;
				}
			}else {
				libs[pkgName]=null;
			}
		}
		await checkDisk("coke");//coke系统磁盘
		await checkDisk("-jaxweb","jaxweb");//jaxweb库磁盘
		await checkDisk("-terminal","terminal");//terminal磁盘
		await checkDisk("-diskit","diskit");//diskit磁盘
		await checkDisk("-desktop","desktop");//desktop磁盘
		await checkDisk("-ccedit","ccedit");//ccedit磁盘
		//await checkDisk("-cody","cody");//cody磁盘
		return libs;
	};
	
	//------------------------------------------------------------------------
	//Install Service-Worker
	CCWorker.installWorker=async function(logger){
		let reg,store,scope,version;
		if(!CCWorker.diskPath){
			//To install，first we install the service-worker:
			logger.state("Installing cokecodes service-worker...");
			logger.log("Start install cokecodes service-worker.");
			scope="/";
			version=appCfg.workerVsnIdx;
			try{
				reg=await navigator.serviceWorker.getRegistration(scope);
				if(reg){
					logger.log("Found existing service-worker, unregister...");
					await reg.unregister();
					logger.log("Existing service-worker, unregister done.");
				}

				logger.log("Registering service-worker...");
				await navigator.serviceWorker.register('../cokeSW.js',{scope:scope,updateViaCache: 'none'});
				console.log("Service-worker registered.");
				if(version>0){
					console.log("Save service-worker version-index: "+version);
					store = new Store('JAXSys', "ServiceWorker");
					await set("version", version, store);
					console.log("Save service-worker version-index done.");
					console.log("Service-worker installation success.");
					return true;
				}
				return true;
			}catch(e){
				logger.log("Install worker error: "+e);
				return false;
			}
		}
		return true;
	};
	
	//------------------------------------------------------------------------
	//Uninstall Service-Worker
	CCWorker.uninstallWorker=async function(logger){
		let scope="/";
		let reg=await navigator.serviceWorker.getRegistration(scope);
		logger.log("Search existing service-worker...");
		if(reg){
			logger.log("Found existing service-worker, unregister...");
			await reg.unregister();
			logger.log("Existing service-worker, unregister done.");
		}
		return true;
	};
	
	//------------------------------------------------------------------------
	//Install system disks:
	CCWorker.installDisks=async function(logger,lib){
		let pmsList=[];
		try{
			//Create sytem "doc" disk
			await JAXDisk.openDisk("doc",1);
			await JAXDisk.setDiskAttr("doc","diskType","System");
			//安装磁盘:
			if(!lib) {
				pmsList.push(CCDisk.installDisk('/download/coke.zip', 'coke', logger));
				pmsList.push(CCDisk.installDisk('/download/jaxweb.zip', '-jaxweb', logger));
				pmsList.push(CCDisk.installDisk('/download/terminal.zip', '-terminal', logger));
				pmsList.push(CCDisk.installDisk('/download/ccedit.zip', '-ccedit', logger));
				pmsList.push(CCDisk.installDisk('/download/diskit.zip', '-diskit', logger));
				pmsList.push(CCDisk.installDisk('/download/desktop.zip', '-desktop', logger));
			}else {
				if(!lib.coke || !lib.coke.checked){
					logger.log("Install disk: coke");
					pmsList.push(CCDisk.installDisk('/download/coke.zip', 'coke', logger,false));
				}else {
					logger.log("disk is ready: coke");
				}
				if(!lib.jaxweb || !lib.jaxweb.checked){
					logger.log("Install disk: -jaxweb");
					pmsList.push(CCDisk.installDisk('/download/jaxweb.zip', '-jaxweb', logger));
				}else {
					logger.log("disk is ready: -jaxweb");
				}
				if(!lib.terminal || !lib.terminal.checked){
					logger.log("Install disk: -terminal");
					pmsList.push(CCDisk.installDisk('/download/terminal.zip', '-terminal', logger));
				}else {
					logger.log("disk is ready: -terminal");
				}
				if(!lib.diskit || !lib.diskit.checked){
					logger.log("Install disk: -diskit");
					pmsList.push(CCDisk.installDisk('/download/diskit.zip', '-diskit', logger));
				}else {
					logger.log("disk is ready: -diskit");
				}
				if(!lib.desktop || !lib.desktop.checked){
					logger.log("Install disk: -desktop");
					pmsList.push(CCDisk.installDisk('/download/desktop.zip', '-desktop', logger));
				}else {
					logger.log("disk is ready: -desktop");
				}
				if(!lib.ccedit || !lib.ccedit.checked){
					logger.log("Install disk: -ccedit");
					pmsList.push(CCDisk.installDisk('/download/ccedit.zip', '-ccedit', logger));
				}else {
					logger.log("disk is ready: -ccedit");
				}
			}
			await Promise.all(pmsList);
			return true;
		}catch(e){
			return false;			
		}
	};
	
	//------------------------------------------------------------------------
	//Drop all disk in sandbox
	CCWorker.dropAllDisks=async function(logger){
		let diskNames,diskName;
		diskNames=await JAXDisk.getDiskNames();
		if(diskNames){
			for(diskName of diskNames){
				logger.log(`Drop disk: ${diskName}`);
				await JAXDisk.dropDisk(diskName,false);
			}
		}
	};
	
	//------------------------------------------------------------------------
	//升级ServiceWorker:
	CCWorker.updateWorker=async function(workerName,version){
		//TODO: Code this:
	};
	/*}#1FD9FKIR00Functions*/
}
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"jaxId": "1FD9FKBJE0", "def": "CdyFileDataClass", 
//			"attrs": {"fileName":"\"CCWorker\"","description":"\"\""}, 
//			"classObjs": {
//				"name": "classObjs", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9FKBJE1", 
//				"attrs": {
//					"CCWorker": {
//						"type": "object", "def": "CdyDataClass", "name": "CCWorker", "tip": "", "jaxId": "1FD9FKIR00", 
//						"attrs": {}, 
//						"args": {
//							"name": "Arguments", "type": "object", "def": "ClassObjArgObj", "jaxId": "1FD9FLQ210", 
//							"attrs": {"superClass":"\"JAXDataObj\""}
//						}, 
//						"pptsObj": {
//							"name": "Properties", "type": "object", "def": "ClassObjPptObj", "jaxId": "1FD9FLQ211", 
//							"attrs": {}
//						}, 
//						"funcsObj": {"jaxId":"1FD9FLQ212","funcs":[]}, 
//						"mockObjs": {
//							"name": "Mockups", "type": "object", "def": "CdyDocObj", "jaxId": "1FD9FLQ213", 
//							"attrs": {}
//						}
//					}
//				}
//			}
//		}/*Doc}#*/;
//	}

//Auto genterated by Cody
/*#{1FDAETMLJ0Imports*/
/*}#1FDAETMLJ0Imports*/
//----------------------------------------------------------------------------
/*按钮控件，支持鼠标悬浮、不可用状态*/
var BtnStd=function (app, w, text, $state){
	let jaxEnv,appCfg,state;
	let cssVO;
	/*#{1FDAETMLJ1ExLocal*/
	/*}#1FDAETMLJ1ExLocal*/
	
	jaxEnv=app.jaxEnv;
	appCfg=app.appCfg;
	
	state={
		"text": text
		/*#{1FDAETMLJ3ExState*/
		/*}#1FDAETMLJ3ExState*/
	};
	if($state){
		Object.assign(state,$state);
	}
	state=jaxHudState(jaxEnv,state);
	
	/*#{1FDAETMLJ1Mid*/
	/*}#1FDAETMLJ1Mid*/
	
	cssVO={
		"type": "button", "jaxId": "1FDAETMLJ1", "x": 106, "y": 129, "w": w, "h": appCfg.size.btnStdH, 
		"hudState": state, 
		"hudBtnUp": {
			"type": "box", "jaxId": "1FDAF6F8M0", "x": 0, "y": 0, "w": "FW", "h": "FH", "autoLayout": 1, "color": appCfg.color.btnStdFace, "coner": 3, "shadow": 1, 
			"shadowX": 1, "shadowY": 1, "shadowBlur": 2, "shadowColor": [0,0,0,0.5]
		},
		"hudBtnDown": {
			"type": "box", "jaxId": "1FDAFQV503", "x": 0, "y": 1, "w": "FW", "h": "FH", "autoLayout": 1, "color": appCfg.color.btnStdDown, "coner": 3, "shadowColor": [0,0,0,0.5]
		},
		"hudBtnGray": {
			"type": "box", "jaxId": "1FDAFQV506", "x": 0, "y": 0, "w": "FW", "h": "FH", "autoLayout": 1, "color": appCfg.color.btnStdGray, "coner": 3, "shadowColor": [0,0,0,0.5]
		},
		items: [
			{
				"type": "text", "jaxId": "1FDAFQV509", "x": 0, "y": 0, "w": 150, "h": 32, "autoLayout": 1, "text": $V(()=>(state.text)),"color": appCfg.color.btnStdText, 
				"alignH": 1, "alignV": 1, "fontSize": appCfg.txtSize.mid
			}
		],
		faces: {
			"up": {
				/**/"#1FDAFQV509": {
					"y": 0
				},
			},
			"down": {
				/**/"#1FDAFQV509": {
					"y": 1
				},
			},
			"gray": {
				/**/"#1FDAFQV509": {
					"y": 0
				},
			}
		},
		OnCreate: function(){
			/*#{1FDAETMLJ1CreateFunc*/
			/*}#1FDAETMLJ1CreateFunc*/
		}
	};
	/*#{1FDAETMLJ1ExViewDef*/
	/*}#1FDAETMLJ1ExViewDef*/
	
	return cssVO;
};
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"type": "object", "name": "BtnStd.js", "def": "CdyFileUIGear", "jaxId": "1FDAETMLJ0", 
//			"attrs": {
//				"gearName": "\"BtnStd\"", "device": "iPhone 375x750", "w": "375", "h": "750", "desc": "\"\"", 
//				"notes": {
//					"type": "object", "def": "HudNote", "jaxId": "1FDAETMLO0", 
//					"attrs": {"locked":"0"}, "faces": null, 
//					"viewFaces": {"jaxId":"1FDAETMLO2","entrys":[]}, "subs": []
//				}
//			}, 
//			"uiGear": {
//				"type": "object", "def": "HudBtn", "jaxId": "1FDAETMLJ1", 
//				"args": {
//					"name": "args", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAETMLJ2", 
//					"attrs": {
//						"w": {"type":"int","valText":"150","initVal":"","info":null,"tip":null}, 
//						"text": {
//							"type": "string", "valText": "\"Button\"", "initVal": "", "info": null, 
//							"tip": null
//						}
//					}
//				}, 
//				"stateObj": {
//					"name": "stateObj", "type": "object", "def": "CdyDocObjHudState", "jaxId": "1FDAETMLJ3", 
//					"attrs": {"text":{"type":"auto","valText":"#text","info":null,"tip":null}}, 
//					"funcs": {"jaxId":"1FDAETMLO3","funcs":[]}
//				}, 
//				"attrs": {
//					"locked": "0", "id": "\"\"", "x": "106", "y": "129", "w": "#w", "h": "#appCfg.size.btnStdH", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//					"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "drag": "NA", "enable": "On"
//				}, 
//				"viewFaces": {
//					"jaxId": "1FDAETMLO4", 
//					"entrys": [
//						{
//							"jaxId": "1FDAFN6OP0", "attrs": {"Face Name":"\"up\"","Face Function":"0"}, 
//							"state": {
//								"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAFQV500", 
//								"attrs": {}
//							}, 
//							"faceTimes": []
//						},
//						{
//							"jaxId": "1FDAFNEE60", "attrs": {"Face Name":"\"down\"","Face Function":"0"}, 
//							"state": {
//								"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAFQV501", 
//								"attrs": {}
//							}, 
//							"faceTimes": []
//						},
//						{
//							"jaxId": "1FDAFNI400", "attrs": {"Face Name":"\"gray\"","Face Function":"0"}, 
//							"state": {
//								"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAFQV502", 
//								"attrs": {}
//							}, 
//							"faceTimes": []
//						}
//					]
//				}, 
//				"funcs": {"jaxId":"1FDAETMLO6","funcs":[]}, 
//				"btnHuds": {
//					"hudBtnUp": {
//						"type": "object", "def": "HudBox", "jaxId": "1FDAF6F8M0", 
//						"attrs": {
//							"locked": "0", "id": "\"\"", "x": "0", "y": "0", "w": "\"FW\"", "h": "\"FH\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "On", "display": "Show", 
//							"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "#appCfg.color.btnStdFace", "border": "0", 
//							"borderStyle": "Solid", "borderColor": "[0,0,0,1]", "coner": "3", "gradient": "\"\"", "shadow": "1", "shadowX": "1", "shadowY": "1", "shadowBlur": "2", 
//							"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//						}, 
//						"funcs": {"jaxId":"1FDAF6F8M2","funcs":[]}, "subs": []
//					}, 
//					"hudBtnDown": {
//						"type": "object", "def": "HudBox", "jaxId": "1FDAFQV503", 
//						"attrs": {
//							"locked": "0", "id": "\"\"", "x": "0", "y": "1", "w": "\"FW\"", "h": "\"FH\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "On", "display": "Show", 
//							"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "#appCfg.color.btnStdDown", "border": "0", 
//							"borderStyle": "Solid", "borderColor": "[0,0,0,1]", "coner": "3", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", 
//							"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//						}, 
//						"funcs": {"jaxId":"1FDAFQV505","funcs":[]}, "subs": []
//					}, 
//					"hudBtnGray": {
//						"type": "object", "def": "HudBox", "jaxId": "1FDAFQV506", 
//						"attrs": {
//							"locked": "0", "id": "\"\"", "x": "0", "y": "0", "w": "\"FW\"", "h": "\"FH\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "On", "display": "Show", 
//							"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "#appCfg.color.btnStdGray", "border": "0", 
//							"borderStyle": "Solid", "borderColor": "[0,0,0,1]", "coner": "3", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", 
//							"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//						}, 
//						"funcs": {"jaxId":"1FDAFQV508","funcs":[]}, "subs": []
//					}
//				}, 
//				"subs": [
//					{
//						"type": "object", "def": "HudTxt", "jaxId": "1FDAFQV509", 
//						"attrs": {
//							"locked": "1", "id": "\"\"", "x": "0", "y": "0", "w": "150", "h": "32", "anchorH": "Left", "anchorV": "Top", "autoLayout": "On", "display": "Show", 
//							"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "text": "${state.text}", "color": "#appCfg.color.btnStdText", 
//							"autoSizeW": "0", "autoSizeH": "0", "select": "0", "wrap": "0", "ellipsis": "0", "alignH": "Center", "alignV": "Center", "font": "\"\"", "fontSize": "#appCfg.txtSize.mid", 
//							"bold": "0", "italic": "0", "underline": "0"
//						}, 
//						"faces": {
//							"jaxId": "1FDAFQV5010", 
//							"entrys": [
//								{
//									"jaxId": "1FDAFQV5011", "entryId": "1FDAFN6OP0", "faceName": "up", 
//									"attrs": {"y":"0"}, 
//									"anis": {
//										"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDAFQV5012", 
//										"attrs": []
//									}
//									
//								},
//								{
//									"jaxId": "1FDAFQV5013", "entryId": "1FDAFNEE60", "faceName": "down", 
//									"attrs": {"y":"1"}, 
//									"anis": {
//										"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDAFQV5014", 
//										"attrs": []
//									}
//									
//								},
//								{
//									"jaxId": "1FDAFQV5015", "entryId": "1FDAFNI400", "faceName": "gray", 
//									"attrs": {"y":"0"}, 
//									"anis": {
//										"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDAFQV5016", 
//										"attrs": []
//									}
//									
//								}
//							]
//						}, 
//						"funcs": {"jaxId":"1FDAFQV5017","funcs":[]}, "subs": []
//					}
//				]
//			}
//		}/*Doc}#*/;
//	}

//>>>>>>Node2Coke>>>>>>
var module$1={exports:{}};
var module=module$1;

var R = typeof Reflect === 'object' ? Reflect : null;
var ReflectApply = R && typeof R.apply === 'function'
	? R.apply
	: function ReflectApply(target, receiver, args) {
		return Function.prototype.apply.call(target, receiver, args);
	};

var ReflectOwnKeys;
if (R && typeof R.ownKeys === 'function') {
	ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
	ReflectOwnKeys = function ReflectOwnKeys(target) {
		return Object.getOwnPropertyNames(target)
			.concat(Object.getOwnPropertySymbols(target));
	};
} else {
	ReflectOwnKeys = function ReflectOwnKeys(target) {
		return Object.getOwnPropertyNames(target);
	};
}

function ProcessEmitWarning(warning) {
	if (console && console.warn) console.warn(warning);
}

var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
	return value !== value;
};

function EventEmitter() {
	EventEmitter.init.call(this);
}
module.exports = EventEmitter;
module.exports.once = once;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10;

function checkListener(listener) {
	if (typeof listener !== 'function') {
		throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
	}
}

Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
	enumerable: true,
	get: function() {
		return defaultMaxListeners;
	},
	set: function(arg) {
		if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
			throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
		}
		defaultMaxListeners = arg;
	}
});

EventEmitter.init = function() {
	
	if (this._events === undefined ||
		this._events === Object.getPrototypeOf(this)._events) {
		this._events = Object.create(null);
		this._eventsCount = 0;
	}
	
	this._maxListeners = this._maxListeners || undefined;
};

// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
	if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
		throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
	}
	this._maxListeners = n;
	return this;
};

function _getMaxListeners(that) {
	if (that._maxListeners === undefined)
		return EventEmitter.defaultMaxListeners;
	return that._maxListeners;
}

EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
	return _getMaxListeners(this);
};

EventEmitter.prototype.emit = function emit(type) {
	var args = [];
	for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
	var doError = (type === 'error');
	
	var events = this._events;
	if (events !== undefined)
		doError = (doError && events.error === undefined);
	else if (!doError)
		return false;
	
	// If there is no 'error' event listener then throw.
	if (doError) {
		var er;
		if (args.length > 0)
			er = args[0];
		if (er instanceof Error) {
			// Note: The comments on the `throw` lines are intentional, they show
			// up in Node's output if this results in an unhandled exception.
			throw er; // Unhandled 'error' event
		}
		// At least give some kind of context to the user
		var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
		err.context = er;
		throw err; // Unhandled 'error' event
	}
	
	var handler = events[type];
	
	if (handler === undefined)
		return false;
	
	if (typeof handler === 'function') {
		ReflectApply(handler, this, args);
	} else {
		var len = handler.length;
		var listeners = arrayClone(handler, len);
		for (var i = 0; i < len; ++i)
			ReflectApply(listeners[i], this, args);
	}
	
	return true;
};

function _addListener(target, type, listener, prepend) {
	var m;
	var events;
	var existing;
	
	checkListener(listener);
	
	events = target._events;
	if (events === undefined) {
		events = target._events = Object.create(null);
		target._eventsCount = 0;
	} else {
		// To avoid recursion in the case that type === "newListener"! Before
		// adding it to the listeners, first emit "newListener".
		if (events.newListener !== undefined) {
			target.emit('newListener', type,
				listener.listener ? listener.listener : listener);
			
			// Re-assign `events` because a newListener handler could have caused the
			// this._events to be assigned to a new object
			events = target._events;
		}
		existing = events[type];
	}
	
	if (existing === undefined) {
		// Optimize the case of one listener. Don't need the extra array object.
		existing = events[type] = listener;
		++target._eventsCount;
	} else {
		if (typeof existing === 'function') {
			// Adding the second element, need to change to array.
			existing = events[type] =
				prepend ? [listener, existing] : [existing, listener];
			// If we've already got an array, just append.
		} else if (prepend) {
			existing.unshift(listener);
		} else {
			existing.push(listener);
		}
		
		// Check for listener leak
		m = _getMaxListeners(target);
		if (m > 0 && existing.length > m && !existing.warned) {
			existing.warned = true;
			// No error code for this since it is a Warning
			// eslint-disable-next-line no-restricted-syntax
			var w = new Error('Possible EventEmitter memory leak detected. ' +
				existing.length + ' ' + String(type) + ' listeners ' +
				'added. Use emitter.setMaxListeners() to ' +
				'increase limit');
			w.name = 'MaxListenersExceededWarning';
			w.emitter = target;
			w.type = type;
			w.count = existing.length;
			ProcessEmitWarning(w);
		}
	}
	
	return target;
}

EventEmitter.prototype.addListener = function addListener(type, listener) {
	return _addListener(this, type, listener, false);
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.prependListener =
	function prependListener(type, listener) {
		return _addListener(this, type, listener, true);
	};

function onceWrapper() {
	if (!this.fired) {
		this.target.removeListener(this.type, this.wrapFn);
		this.fired = true;
		if (arguments.length === 0)
			return this.listener.call(this.target);
		return this.listener.apply(this.target, arguments);
	}
}

function _onceWrap(target, type, listener) {
	var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
	var wrapped = onceWrapper.bind(state);
	wrapped.listener = listener;
	state.wrapFn = wrapped;
	return wrapped;
}

EventEmitter.prototype.once = function once(type, listener) {
	checkListener(listener);
	this.on(type, _onceWrap(this, type, listener));
	return this;
};

EventEmitter.prototype.prependOnceListener =
	function prependOnceListener(type, listener) {
		checkListener(listener);
		this.prependListener(type, _onceWrap(this, type, listener));
		return this;
	};

// Emits a 'removeListener' event if and only if the listener was removed.
EventEmitter.prototype.removeListener =
	function removeListener(type, listener) {
		var list, events, position, i, originalListener;
		
		checkListener(listener);
		
		events = this._events;
		if (events === undefined)
			return this;
		
		list = events[type];
		if (list === undefined)
			return this;
		
		if (list === listener || list.listener === listener) {
			if (--this._eventsCount === 0)
				this._events = Object.create(null);
			else {
				delete events[type];
				if (events.removeListener)
					this.emit('removeListener', type, list.listener || listener);
			}
		} else if (typeof list !== 'function') {
			position = -1;
			
			for (i = list.length - 1; i >= 0; i--) {
				if (list[i] === listener || list[i].listener === listener) {
					originalListener = list[i].listener;
					position = i;
					break;
				}
			}
			
			if (position < 0)
				return this;
			
			if (position === 0)
				list.shift();
			else {
				spliceOne(list, position);
			}
			
			if (list.length === 1)
				events[type] = list[0];
			
			if (events.removeListener !== undefined)
				this.emit('removeListener', type, originalListener || listener);
		}
		
		return this;
	};

EventEmitter.prototype.off = EventEmitter.prototype.removeListener;

EventEmitter.prototype.removeAllListeners =
	function removeAllListeners(type) {
		var listeners, events, i;
		
		events = this._events;
		if (events === undefined)
			return this;
		
		// not listening for removeListener, no need to emit
		if (events.removeListener === undefined) {
			if (arguments.length === 0) {
				this._events = Object.create(null);
				this._eventsCount = 0;
			} else if (events[type] !== undefined) {
				if (--this._eventsCount === 0)
					this._events = Object.create(null);
				else
					delete events[type];
			}
			return this;
		}
		
		// emit removeListener for all listeners on all events
		if (arguments.length === 0) {
			var keys = Object.keys(events);
			var key;
			for (i = 0; i < keys.length; ++i) {
				key = keys[i];
				if (key === 'removeListener') continue;
				this.removeAllListeners(key);
			}
			this.removeAllListeners('removeListener');
			this._events = Object.create(null);
			this._eventsCount = 0;
			return this;
		}
		
		listeners = events[type];
		
		if (typeof listeners === 'function') {
			this.removeListener(type, listeners);
		} else if (listeners !== undefined) {
			// LIFO order
			for (i = listeners.length - 1; i >= 0; i--) {
				this.removeListener(type, listeners[i]);
			}
		}
		
		return this;
	};

function _listeners(target, type, unwrap) {
	var events = target._events;
	
	if (events === undefined)
		return [];
	
	var evlistener = events[type];
	if (evlistener === undefined)
		return [];
	
	if (typeof evlistener === 'function')
		return unwrap ? [evlistener.listener || evlistener] : [evlistener];
	
	return unwrap ?
		unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}

EventEmitter.prototype.listeners = function listeners(type) {
	return _listeners(this, type, true);
};

EventEmitter.prototype.rawListeners = function rawListeners(type) {
	return _listeners(this, type, false);
};

EventEmitter.listenerCount = function(emitter, type) {
	if (typeof emitter.listenerCount === 'function') {
		return emitter.listenerCount(type);
	} else {
		return listenerCount.call(emitter, type);
	}
};

EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
	var events = this._events;
	
	if (events !== undefined) {
		var evlistener = events[type];
		
		if (typeof evlistener === 'function') {
			return 1;
		} else if (evlistener !== undefined) {
			return evlistener.length;
		}
	}
	
	return 0;
}

EventEmitter.prototype.eventNames = function eventNames() {
	return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};

function arrayClone(arr, n) {
	var copy = new Array(n);
	for (var i = 0; i < n; ++i)
		copy[i] = arr[i];
	return copy;
}

function spliceOne(list, index) {
	for (; index + 1 < list.length; index++)
		list[index] = list[index + 1];
	list.pop();
}

function unwrapListeners(arr) {
	var ret = new Array(arr.length);
	for (var i = 0; i < ret.length; ++i) {
		ret[i] = arr[i].listener || arr[i];
	}
	return ret;
}

function once(emitter, name) {
	return new Promise(function (resolve, reject) {
		function errorListener(err) {
			emitter.removeListener(name, resolver);
			reject(err);
		}
		
		function resolver() {
			if (typeof emitter.removeListener === 'function') {
				emitter.removeListener('error', errorListener);
			}
			resolve([].slice.call(arguments));
		}		
		eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
		if (name !== 'error') {
			addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
		}
	});
}

function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
	if (typeof emitter.on === 'function') {
		eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
	}
}

function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
	if (typeof emitter.on === 'function') {
		if (flags.once) {
			emitter.once(name, listener);
		} else {
			emitter.on(name, listener);
		}
	} else if (typeof emitter.addEventListener === 'function') {
		// EventTarget does not have `error` event semantics like Node
		// EventEmitters, we do not listen for `error` events here.
		emitter.addEventListener(name, function wrapListener(arg) {
			// IE does not have builtin `{ once: true }` support so we
			// have to do it manually.
			if (flags.once) {
				emitter.removeEventListener(name, wrapListener);
			}
			listener(arg);
		});
	} else {
		throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
	}
}
module$1.exports['once'];
//<<<<<<Node2Coke<<<<<<

var CokeFrame,cokeFrame,liveFrames,nextSeq;

liveFrames={};
nextSeq=1;
//***************************************************************************
//Coke Frame
//***************************************************************************
{
	CokeFrame=function(){
		let ifm,seq;
		EventEmitter.call(this);
		seq=""+(nextSeq++);
		this.frame=ifm=document.createElement("iframe");
		ifm.src=`${document.location.origin}//-terminal/frame.html?${seq}`;
		this.frameStub=liveFrames[seq]={
			cokeFrame:this,seq:seq,frame:ifm,client:null
		};
		this.inCmd=false;
	};
	cokeFrame=CokeFrame.prototype=new EventEmitter();
	
	//-----------------------------------------------------------------------
	//Bind CokeFrame to a div:
	cokeFrame.createFrame=function(div){
		let ifm;
		ifm=this.frame;
		this.frameDiv=div;
		ifm.style.position="absolute";
		ifm.style.left="0px";
		ifm.style.top="0px";
		ifm.style.width="100%";
		ifm.style.height="100%";
		ifm.style.border="none";
		div.appendChild(ifm);
	};
	
	//-----------------------------------------------------------------------
	//Exec a command line in client iframe:
	cokeFrame.execCmd=function(text){
		return new Promise((resolve,reject)=>{
			let doneCbk,errorCbk,self;
			self=this;
			doneCbk=function(data){
				self.inCmd=false;
				this.off("ExecCommandDone",doneCbk);
				this.off("ExecCommandError",errorCbk);
				resolve(data);
				if(!self.inCmd){
					self.emit("ShellIdle");
				}
			};
			errorCbk=function(data){
				self.inCmd=false;
				this.off("ExecCommandDone",doneCbk);
				this.off("ExecCommandError",errorCbk);
				resolve(data);
				if(!self.inCmd){
					self.emit("ShellIdle");
				}
			};
			if(this.inCmd){
				reject(new Error("CokeFrame is executing another command."));
				return;
			}
			if(!this.frameStub.client){
				reject(new Error("CokeFrame is not ready yet."));
				return;
			}
			this.inCmd=true;
			this.on("ExecCommandDone",doneCbk);
			this.on("ExecCommandError",errorCbk);
			this.frameStub.client.postMessage({
				msgCatalog:"CokeFrameH2C",
				msg:"ExecCommand",
				cmd:text
			});
			
		});
	};
	
	//-----------------------------------------------------------------------
	//Wait cmd to finish:
	cokeFrame.waitCmd=function() {
		return new Promise((resolve,reject)=>{
			let doneCbk;
			doneCbk=function(){
				resolve();
				this.off("ShellIdle",doneCbk);
			};
			if(!this.inCmd){
				resolve();
				return;
			}
			this.on("ShellIdle",doneCbk);
		});
	};
	
	//-----------------------------------------------------------------------
	//Start user input command:
	cokeFrame.startInputCmd=function(){
		this.inCmd=false;
		this.frameStub.client.postMessage({
			msgCatalog:"CokeFrameH2C",
			msg:"StartInputCmd",
		});
	};
	
	//-----------------------------------------------------------------------
	//Handle client2Host messages:
	window.addEventListener("message",async (evt)=>{
		let seq,stub,frame;
		//Filter messages:
		if(evt.data.msgCatalog!=="CokeFrameC2H"){
			return;
		}
		seq=evt.data.frameSeq;
		stub=liveFrames[seq];
		if(!stub){
			return;
		}
		frame=stub.frame;
		if(!frame){
			return;
		}
		switch(evt.data.msg){
			case "ClientReady": {
				stub.client=evt.source;
				stub.cokeFrame.emit("ClientReady");
				break;
			}
			case "ExecCommandDone": {
				if(stub.cokeFrame.execError) {
					stub.cokeFrame.emit("ExecCommandError",evt.data.msg.error);
				}else {
					stub.cokeFrame.emit("ExecCommandDone",evt.data.msg.result);
				}
				break;
			}
		}
	},false);
}

//Auto genterated by Cody

const STAGE_CHECK="check";				//Checking versions
const STAGE_INSTALL="install";			//Need install
const STAGE_UPDATE="update";			//Can update
const STAGE_ERROR="error";				//Error
const STAGE_CHECKED="checked";			//Version all checked
const STAGE_INSTALLED="installed";		//Install done
const STAGE_UPDATED="updated";			//Update done

//----------------------------------------------------------------------------
//Parse URL params:
let appParams;
{
	let pos;
	let appURL=document.location.href;
	appParams={};
	if(appURL.indexOf("localhost")>=0){
		appParams.debug=true;
	}
	pos=appURL.indexOf("?");
	if(pos<0){
		pos=appURL.indexOf("#");
	}
	if(pos>0){
		let ptext,list;
		ptext=appURL.substring(pos+1);
		list=ptext.split("&");
		list.forEach(item=>{
			let subs,key,val;
			subs=item.split("=");
			if(subs.length===2){
				key=decodeURIComponent(subs[0]);
				val=decodeURIComponent(subs[1]);
				appParams[key]=val;
			}
		});
	}
}

var chrome;
{
	//Check platform and set shortcut
	let userAgent = navigator.userAgent;
	var edge = /Edge\/(\d+)/.exec(userAgent);
	chrome = !edge && /Chrome\//.test(userAgent);
}
/*}#1FDAD06P60Imports*/

/*App界面*/
//----------------------------------------------------------------------------
/*App里的UI View*/
var UIInstall=function (app){
	let jaxEnv,appCfg,state;
	let cssVO,self;
	let stage=null;
	let divLogs=null;
	let stateDiv=null;
	/*}#1FDAD06P70ExLocal*/
	
	jaxEnv=app.jaxEnv;
	appCfg=app.appCfg;
	
	state=jaxHudState(jaxEnv,{
		/*#{1FDAD06P72ExState*/
		/*}#1FDAD06P72ExState*/
	},);
	/*#{1FDAD06P70PostState*/
	let checkLibs=null;
	/*}#1FDAD06P70PostState*/
	
	cssVO={
		"type": "view", "hudState": state, "jaxId": "1FDAD06P70",
		"locked": 0, "x": 0, "y": 0, "w": "FW", "h": "FH", "autoLayout": 1,
		items: [
			{
				"type": "text", "jaxId": "1FDAETASS0", "id": "TextInfo", "x": 32, "y": 50, "w": 962, "h": 28, "text": "Checking dev-tools ...", "color": [0,0,0],
				"fontSize": appCfg.txtSize.big
			},
			{
				"type": "hud", "jaxId": "1FDAETASS3", "id": "BoxVersions", "x": 32, "y": 80, "w": "FW-64", "h": "FH-190",
				items: [
					{
						"type": BtnStd(app,150,"Install",null),"jaxId": "1FDAFVKI10",
						"locked": 0, "id": "BtnInstall", "x": 0, "y": "FH+10",
						//函数
						OnClick:function(){
							/*#{1FDCD28UG0Code*/
							self.startWork();
							/*}#1FDCD28UG0Code*/
						}
					},
					{
						"type": BtnStd(app,150,"Re-install",null),"jaxId": "1FDN43DEN3",
						"locked": 0, "id": "BtnReinstall", "x": 176, "y": "FH+10",
						//函数
						OnClick:function(){
							/*#{1FDN4616Q0Code*/
							self.DoInstall();
							/*}#1FDN4616Q0Code*/
						}
					}
				]
			},
			{
				"type": "hud", "jaxId": "1FDCCENOJ0", "id": "BoxLog", "x": 32, "y": 80, "w": "FW-64", "h": "FH-200",
				items: [
					{
						"type": "box", "jaxId": "1FOS177MB0", "id": "BG", "x": -5, "y": -5, "w": "FW+10", "h": "FH+10", "clip": 1, "color": [255,255,255,1], "border": 1,
						"borderColor": [79,79,79,1], "coner": 4, "shadow": 1, "shadowX": 0, "shadowBlur": 8, "shadowColor": [0,0,0,0.5],
						items: [
							{
								"type": "box", "jaxId": "1FOS47NBG0", "x": 0, "y": 0, "w": "FW", "h": 24, "color": [255,255,255,1], "borderColor": [56,56,56,1], "gradient": "linear-gradient(#E8E8E8, #B0B0B0)",
								"shadowColor": [0,0,0,0.5],
								items: [
									{
										"type": "box", "jaxId": "1FOS4J9FH3", "x": 0, "y": 24, "w": "FW", "h": 1, "color": [80,80,80,1], "shadowColor": [0,0,0,0.5]
									},
									{
										"type": "box", "jaxId": "1FOS6C0QN0", "x": 6, "y": 4, "w": 16, "h": 16, "color": [190,190,190,1], "border": 1, "borderColor": [80,80,80,1],
										"coner": 8, "shadowColor": [0,0,0,0.5]
									},
									{
										"type": "box", "jaxId": "1FOS6C1VI0", "x": 26, "y": 4, "w": 16, "h": 16, "color": [190,190,190,1], "border": 1, "borderColor": [80,80,80,1],
										"coner": 8, "shadowColor": [0,0,0,0.5]
									},
									{
										"type": "box", "jaxId": "1FOS6CM6P0", "x": 46, "y": 4, "w": 16, "h": 16, "color": [190,190,190,1], "border": 1, "borderColor": [80,80,80,1],
										"coner": 8, "shadowColor": [0,0,0,0.5]
									},
									{
										"type": "image", "jaxId": "1FOS7N8VE0", "x": 80, "y": 1, "w": 22, "h": 22, "image": "assets/home.svg", "autoSize": 0, "fitSize": 1
									}
								]
							},
							{
								"type": "box", "jaxId": "1FOS9FLH20", "x": 0, "y": "FH-20", "w": "FW", "h": 20, "color": [200,200,200,1], "shadowColor": [0,0,0,0.5],
								items: [
									{
										"type": "box", "jaxId": "1FOS9GC3A0", "x": 0, "y": 0, "w": "FW", "h": 1, "color": [80,80,80,1], "shadowColor": [0,0,0,0.5]
									},
									{
										"type": "text", "jaxId": "1FOS9QEC12", "id": "TxtBtm", "x": 10, "y": 0, "w": 950, "h": 20, "text": "Setup may take a moment to complete on Chrome",
										"color": [60,60,60], "alignV": 1, "fontSize": 14
									}
								]
							}
						]
					},
					{
						"type": "text", "jaxId": "1FDCCV4S50", "id": "TxtState", "x": 100, "y": 0, "w": "FW", "h": 20, "text": "setup --- setup.sh --- 80x25", "color": [0,0,0],
						"fontSize": appCfg.txtSize.mid
					},
					{
						"type": "hud", "jaxId": "1FOS3E92J0", "id": "BoxLogText", "x": 0, "y": 24, "w": "FW", "h": "FH-48"
					}
				]
			},
			{
				"type": "hud", "jaxId": "1FLPI9OUT1", "id": "BoxFrame", "x": 32, "y": 105, "w": "FW-64", "h": "FH-250"
			},
			{
				"type": "text", "jaxId": "1FOS8BIST0", "x": 30, "y": 10, "w": 956, "h": 20, "text": "CokeCodes Concept", "color": [180,180,180], "fontSize": 28
			}
		],
		faces: {
			"check": {
				"$":function(vo){
					/*#{1FDBIT1P10Func*/
					stage=STAGE_CHECK;
					/*}#1FDBIT1P10Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Checking dev-tools..."
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"install": {
				"$":function(vo){
					/*#{1FDBIUSNA0Func*/
					stage=STAGE_INSTALL;
					/*}#1FDBIUSNA0Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Install dev-tools"
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 1
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Install"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"update": {
				"$":function(vo){
					/*#{1FDBJ276J0Func*/
					stage=STAGE_UPDATE;
					/*}#1FDBJ276J0Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Dev-tools update available"
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 1
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Update"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"checked": {
				"$":function(vo){
					/*#{1FDBKAE2F0Func*/
					stage=STAGE_CHECKED;
					/*}#1FDBKAE2F0Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Your dev-tools is checked"
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 1
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Goto Desktop"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 1
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"installed": {
				"$":function(vo){
					/*#{1FDBKDMT60Func*/
					stage=STAGE_INSTALLED;
					/*}#1FDBKDMT60Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Dev-tools installed"
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 1
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Goto Desktop"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"updated": {
				"$":function(vo){
					/*#{1FDBKDTLG0Func*/
					stage=STAGE_UPDATED;
					/*}#1FDBKDTLG0Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Dev-tools updated"
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Goto Desktop"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			},
			"error": {
				"$":function(vo){
					/*#{1FDBKRPJL0Func*/
					stage=STAGE_ERROR;
					/*}#1FDBKRPJL0Func*/
				},
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Task failed by error"
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 1
				},
				/*BtnInstall*/"#1FDAFVKI10": {
					"%text": "Retry"
				},
				/*BtnReinstall*/"#1FDN43DEN3": {
					"display": 0
				},
			},
			"work": {
				/*TextInfo*/"#1FDAETASS0": {
					"text": "Installing dev-tools..."
				},
				/*BoxVersions*/"#1FDAETASS3": {
					"display": 0
				},
				/*BoxLog*/"#1FDCCENOJ0": {
					"display": 1
				},
			}
		},
		/*#{1FDAD06P70ExAttrs*/
		/*}#1FDAD06P70ExAttrs*/
		OnCreate: function(){
			self=this;
			/*#{1FDAD06P70CreateFunc*/
			divLogs=this.BoxLogText.webObj;
			divLogs.style.overflowY="scroll";
			divLogs.style.overflowX="hidden";
			//divLogs.style.fontFamily="\"Menlo\", monospace";
			divLogs.style.fontFamily='monospace';
			divLogs.style.fontWeight="lighter";
			divLogs.style.fontSize="14px";
			if(chrome){
				self.TxtBtm.text="Setup may take a moment to complete on Chrome.";
			}else {
				self.TxtBtm.text="Work on web? Let's wrok in it!";
			}
			/*}#1FDAD06P70CreateFunc*/
			
		}
	};
	/*#{1FDAD06P70ExViewDef*/
	//------------------------------------------------------------------------
	//显示界面:
	cssVO.showUI=function(vo){
		self.showFace("check");
		self.clear();
		window.setTimeout(()=>{
			self.title("check.sh");
			if(appParams.clear==="true"){
				if(appParams.debug){
					if(!window.confirm("Are you sure to clear sandbox in localhost???")){
						return;
					}
					if(!window.confirm("Are you really sure to clear sandbox in localhost???")){
						return;
					}
				}
				self.DoClear().then(()=>{
					self.title("cleared");
					self.log("Sandbox cleared");
					if(appParams.install!=="false"){
						//Not clear only, also install:
						self.showFace("install");
						if(!appParams.debug){
							self.startWork();
						}
						return;
					}
					self.showFace("install");
				});
				return;
			}
			CCWorker.checkWorker().then(workerReady=>{
				//得到JAXLib和JAXExt的版本号
				if(workerReady){
					self.log("Service worker installed.");
					self.checkDisks().then((isInstalled)=>{
						if(isInstalled){
							if(appParams.path){
								document.location.href=document.location.origin+appParams.path;
							}else {
								document.location.href=document.location.origin+"/@desktop";
							}
						}else {
							self.showFace("install");
							if(!appParams.debug){
								self.startWork();
							}
						}
					});
				}else {
					//Show install tool-chain UI
					self.log("Service worker not installed.");
					self.checkDisks().then((isInstalled)=>{
						self.showFace("install");
						if (!appParams.debug) {
							self.startWork();
						}
					});
				}
			});
		},200);
	};
	
	//------------------------------------------------------------------------
	//检查系统工具磁盘:
	cssVO.checkDisks=async function(){
		let libs,isAllChecked,isPartChecked;
		libs=await CCWorker.checkLibs();
		self.log("Coke: "+(libs.coke?`${libs.coke.version}, ${libs.coke.checked?"checked":"update available."}`:"not installed."));
		self.log("JAXWeb: "+(libs.jaxweb?`${libs.jaxweb.version}, ${libs.jaxweb.checked?"checked":"update available."}`:"not installed."));
		self.log("Terminal: "+(libs.terminal?`${libs.terminal.version}, ${libs.terminal.checked?"checked":"update available."}`:"not installed."));
		self.log("Desktop: "+(libs.desktop?`${libs.desktop.version}, ${libs.desktop.checked?"checked":"update available."}`:"not installed."));
		self.log("Distkit: "+(libs.diskit?`${libs.diskit.version}, ${libs.diskit.checked?"checked":"update available."}`:"not installed."));
		self.log("CCEdit: "+(libs.ccedit?`${libs.ccedit.version}, ${libs.ccedit.checked?"checked":"update available."}`:"not installed."));
		checkLibs=libs;
		isAllChecked=libs.coke&&libs.coke.checked&&
			libs.jaxweb&&libs.jaxweb.checked&&
			libs.terminal&&libs.terminal.checked&&
			libs.desktop&&libs.desktop.checked&&
			libs.ccedit&&libs.ccedit.checked&&
			libs.diskit&&libs.diskit.checked;
		isPartChecked=(libs.coke&&libs.coke.checked)||
			(libs.jaxweb&&libs.jaxweb.checked)||
			(libs.terminal&&libs.terminal.checked)||
			(libs.desktop&&libs.desktop.checked)||
			(libs.ccedit&&libs.ccedit.checked)||
			(libs.diskit&&libs.diskit.checked);
		if(isAllChecked && isAllChecked){
			return 2;
		}
		if(isPartChecked){
			return 1;
		}
		return 0;
	};
	
	//------------------------------------------------------------------------
	//根据当前状态，开始安装/进入桌面
	cssVO.startWork=function(){
		switch(stage){
			case STAGE_INSTALL:
				//Start install:
				return self.DoInstall();
			case STAGE_CHECKED:
			case STAGE_INSTALLED:
				if(appParams.path){
					document.location.href=document.location.origin+appParams.path;
				}else {
					document.location.href = document.location.origin + "/@desktop";
				}
				break;
		}
	};
	
	//------------------------------------------------------------------------
	//Start install system:
	cssVO.DoInstall=async function(){
		let installPMS;
		self.showFace("work");
		self.clear();
		self.title("setup-sw.sh");
		if(!await CCWorker.installWorker(self)){
			//安装Service-worker失败:
			self.title("Install service worker failed, check logs for details");
			return;
		}
		self.title("setup-disks.sh");
		installPMS=CCWorker.installDisks(self,checkLibs);
		if(!(await installPMS)){
			//Install failed:
			self.title("Install tool disk image failed, check logs for details");
			return;
		}
		self.clear();
		self.title("wait-sw.sh");
		setTimeout(async ()=>{
			self.showFace("installed");
			self.startWork();
		},100);
	};
	
	//------------------------------------------------------------------------
	//Start clear sandbox:
	cssVO.DoClear=async function(){
		self.showFace("work");
		self.clear();
		self.title("clear-sw.sh");
		await CCWorker.dropAllDisks(self);
		await CCWorker.uninstallWorker(self);
		return true;
	};
	
	//------------------------------------------------------------------------
	//Clear logs:
	cssVO.clear=function(text){
		divLogs.innerText="";
		divLogs.scrollTop = divLogs.scrollHeight;
	};
	
	//------------------------------------------------------------------------
	//Output log:
	cssVO.log=function(text){
		let div;
		div=document.createElement("div");
		div.style.fontFamily='monospace';
		div.style.fontWeight="lighter";
		div.style.fontSize="14px";
		div.innerText=text;
		divLogs.appendChild(div);
		stateDiv=null;
		
		//logs+=text+"\n";
		//divLogs.innerText=logs;
		divLogs.scrollTop = divLogs.scrollHeight;
	};
	
	//------------------------------------------------------------------------
	//Update terminal title:
	cssVO.title=function(text){
		self.TxtState.text=`setup --- ${text} --- 80x25`;
	};
	
	//------------------------------------------------------------------------
	//Show a state, if there is a state, change it:
	cssVO.state=function(text){
		let div;
		if(stateDiv){
			stateDiv.innerText=text;
			return;
		}
		div=document.createElement("div");
		div.style.fontFamily='monospace';
		div.style.fontWeight="lighter";
		div.style.fontSize="14px";
		div.innerText=text;
		divLogs.appendChild(div);
		stateDiv=div;
		
		divLogs.scrollTop = divLogs.scrollHeight;
	};
	
	/*}#1FDAD06P70ExViewDef*/
	
	return cssVO;
};
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"name": "UIInstall.js", "type": "object", "def": "CdyFileUIView", "jaxId": "1FDAD06P60", 
//			"attrs": {
//				"viewName": "\"UIInstall\"", "device": "Custom size", "w": "1024", "h": "600", 
//				"view": {
//					"type": "object", "def": "HudView", "jaxId": "1FDAD06P70", 
//					"args": {
//						"name": "args", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAD06P71", 
//						"attrs": {}
//					}, 
//					"stateObj": {
//						"name": "state", "type": "object", "def": "CdyDocObjHudState", "jaxId": "1FDAD06P72", 
//						"attrs": {}, "funcs": {"jaxId":"1FDAD06P73","funcs":[]}
//					}, 
//					"attrs": {
//						"locked": "0", "viewName": "\"uiView\"", "x": "0", "y": "0", "w": "\"FW\"", "h": "\"FH\"", "autoLayout": "On"
//					}, 
//					"faces": null, 
//					"viewFaces": {
//						"jaxId": "1FDAD06P75", 
//						"entrys": [
//							{
//								"jaxId": "1FDBIT1P10", "attrs": {"Face Name":"\"check\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q0", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBIUSNA0", 
//								"attrs": {"Face Name":"\"install\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q1", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBJ276J0", 
//								"attrs": {"Face Name":"\"update\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q2", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBKAE2F0", 
//								"attrs": {"Face Name":"\"checked\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q3", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBKDMT60", 
//								"attrs": {"Face Name":"\"installed\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q4", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBKDTLG0", 
//								"attrs": {"Face Name":"\"updated\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q5", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDBKRPJL0", "attrs": {"Face Name":"\"error\"","Face Function":"1"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDBL4U8Q6", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							},
//							{
//								"jaxId": "1FDCCC2J50", "attrs": {"Face Name":"\"work\"","Face Function":"0"}, 
//								"state": {
//									"name": "state", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDCCGGGK0", 
//									"attrs": {}
//								}, 
//								"faceTimes": []
//							}
//						]
//					}, 
//					"funcs": {"jaxId":"1FDAD06P76","funcs":[]}, 
//					"subs": [
//						{
//							"type": "object", "def": "HudTxt", "jaxId": "1FDAETASS0", 
//							"attrs": {
//								"locked": "0", "id": "\"TextInfo\"", "x": "32", "y": "50", "w": "962", "h": "28", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//								"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "text": "\"Checking dev-tools ...\"", "color": "[0,0,0]", 
//								"autoSizeW": "0", "autoSizeH": "0", "select": "0", "wrap": "0", "ellipsis": "0", "alignH": "Left", "alignV": "Top", "font": "\"\"", "fontSize": "#appCfg.txtSize.big", 
//								"bold": "0", "italic": "0", "underline": "0"
//							}, 
//							"faces": {
//								"jaxId": "1FDAG9B4P1", 
//								"entrys": [
//									{
//										"jaxId": "1FDBL4U8Q7", "entryId": "1FDBIT1P10", "faceName": "check", 
//										"attrs": {"text":"\"Checking dev-tools...\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q8", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q9", "entryId": "1FDBJ276J0", "faceName": "update", 
//										"attrs": {"text":"\"Dev-tools update available\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q10", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q11", "entryId": "1FDBIUSNA0", "faceName": "install", 
//										"attrs": {"text":"\"Install dev-tools\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q12", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q13", "entryId": "1FDBKAE2F0", "faceName": "checked", 
//										"attrs": {"text":"\"Your dev-tools is checked\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q14", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q15", "entryId": "1FDBKDMT60", "faceName": "installed", 
//										"attrs": {"text":"\"Dev-tools installed\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q16", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q17", "entryId": "1FDBKDTLG0", "faceName": "updated", 
//										"attrs": {"text":"\"Dev-tools updated\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q18", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q19", "entryId": "1FDBKRPJL0", "faceName": "error", 
//										"attrs": {"text":"\"Task failed by error\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q20", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL0", "entryId": "1FDCCC2J50", "faceName": "work", 
//										"attrs": {"text":"\"Installing dev-tools...\""}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL1", 
//											"attrs": []
//										}
//										
//									}
//								]
//							}, 
//							"funcs": {"jaxId":"1FDAETASS2","funcs":[]}, "subs": []
//						},
//						{
//							"type": "object", "def": "HudObj", "jaxId": "1FDAETASS3", 
//							"attrs": {
//								"locked": "0", "id": "\"BoxVersions\"", "x": "32", "y": "80", "w": "\"FW-64\"", "h": "\"FH-190\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//								"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0"
//							}, 
//							"faces": {
//								"jaxId": "1FDAG9B4P2", 
//								"entrys": [
//									{
//										"jaxId": "1FDBL4U8Q21", "entryId": "1FDBIT1P10", "faceName": "check", 
//										"attrs": {"display":"Hide"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q22", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q23", "entryId": "1FDBJ276J0", "faceName": "update", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q24", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q25", "entryId": "1FDBIUSNA0", "faceName": "install", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q26", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q27", "entryId": "1FDBKAE2F0", "faceName": "checked", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q28", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDBL4U8Q29", "entryId": "1FDBKRPJL0", "faceName": "error", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q30", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL2", "entryId": "1FDCCC2J50", "faceName": "work", 
//										"attrs": {"display":"Hide"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL3", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDGSMJF60", "entryId": "1FDBKDMT60", "faceName": "installed", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDGSMJF61", 
//											"attrs": []
//										}
//										
//									}
//								]
//							}, 
//							"funcs": {"jaxId":"1FDAETASS5","funcs":[]}, 
//							"subs": [
//								{
//									"type": "object", "def": "Gear1FDAETMLJ0", "jaxId": "1FDAFVKI10", 
//									"args": {
//										"name": "gearArgs", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAFVKI11", 
//										"attrs": {
//											"w": {"type":"int","valText":"150","initVal":0,"info":null,"tip":null}, 
//											"text": {
//												"type": "string", "valText": "\"Install\"", "initVal": "", "info": null, 
//												"tip": null
//											}
//										}
//									}, 
//									"stateObj": {
//										"name": "gearState", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDAFVKI12", 
//										"attrs": {}
//									}, 
//									"attrs": {
//										"locked": {"type":"auto","valText":"0","info":"","tip":""}, "id": "\"BtnInstall\"", "x": "0", "y": "\"FH+10\"", "autoLayout": "Off"
//									}, 
//									"faces": {
//										"jaxId": "1FDAG9B4P6", 
//										"entrys": [
//											{
//												"jaxId": "1FDBL4U8Q31", "entryId": "1FDBIUSNA0", "faceName": "install", 
//												"attrs": {
//													"[state].text": {"type":"auto","valText":"\"Install\"","info":null,"tip":null}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q32", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDBL4U8Q33", "entryId": "1FDBJ276J0", "faceName": "update", 
//												"attrs": {
//													"[state].text": {"type":"auto","valText":"\"Update\"","info":null,"tip":null}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q34", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDBL4U8Q35", "entryId": "1FDBKAE2F0", "faceName": "checked", 
//												"attrs": {
//													"[state].text": {
//														"type": "auto", "valText": "\"Goto Desktop\"", "initVal": undefined, 
//														"info": null, "tip": null
//													}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q36", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDBL4U8Q37", "entryId": "1FDBKDMT60", "faceName": "installed", 
//												"attrs": {
//													"[state].text": {
//														"type": "auto", "valText": "\"Goto Desktop\"", "initVal": undefined, 
//														"info": null, "tip": null
//													}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q38", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDBL4U8Q39", "entryId": "1FDBKDTLG0", "faceName": "updated", 
//												"attrs": {
//													"[state].text": {
//														"type": "auto", "valText": "\"Goto Desktop\"", "initVal": undefined, 
//														"info": null, "tip": null
//													}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q40", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDBL4U8Q41", "entryId": "1FDBKRPJL0", "faceName": "error", 
//												"attrs": {
//													"[state].text": {"type":"auto","valText":"\"Retry\"","info":null,"tip":null}
//												}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDBL4U8Q42", 
//													"attrs": []
//												}
//												
//											}
//										]
//									}, 
//									"funcs": {
//										"jaxId": "1FDAFVKI14", 
//										"funcs": [
//											{
//												"jaxId": "1FDCD28UG0", "type": "object", "def": "CdyFunc", "name": "OnClick", "info": "函数", "tip": "", 
//												"args": {
//													"name": "args", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDCD2GTP0", 
//													"attrs": {}
//												}, 
//												"attrs": {"Mockup Result":"\"\""}
//											}
//										]
//									}
//									
//								},
//								{
//									"type": "object", "def": "Gear1FDAETMLJ0", "jaxId": "1FDN43DEN3", 
//									"args": {
//										"name": "gearArgs", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDN43DEN4", 
//										"attrs": {
//											"w": {"type":"int","valText":"150","initVal":0,"info":null,"tip":null}, 
//											"text": {
//												"type": "string", "valText": "\"Re-install\"", "initVal": "", 
//												"info": null, "tip": null
//											}
//										}
//									}, 
//									"stateObj": {
//										"name": "gearState", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDN43DEN5", 
//										"attrs": {}
//									}, 
//									"attrs": {
//										"locked": {"type":"auto","valText":"0","info":"","tip":""}, "id": "\"BtnReinstall\"", "x": "176", "y": "\"FH+10\"", "autoLayout": "Off"
//									}, 
//									"faces": {
//										"jaxId": "1FDN43DEN6", 
//										"entrys": [
//											{
//												"jaxId": "1FDN43DEN7", "entryId": "1FDBIUSNA0", "faceName": "install", 
//												"attrs": {"display":"Off"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN8", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDN43DEN9", "entryId": "1FDBJ276J0", "faceName": "update", 
//												"attrs": {"display":"Off"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN10", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDN43DEN11", "entryId": "1FDBKAE2F0", "faceName": "checked", 
//												"attrs": {"display":"On"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN12", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDN43DEN13", "entryId": "1FDBKDMT60", "faceName": "installed", 
//												"attrs": {"display":"Off"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN14", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDN43DEN15", "entryId": "1FDBKDTLG0", "faceName": "updated", 
//												"attrs": {"display":"Off"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN16", 
//													"attrs": []
//												}
//												
//											},
//											{
//												"jaxId": "1FDN43DEN17", "entryId": "1FDBKRPJL0", "faceName": "error", 
//												"attrs": {"display":"Off"}, 
//												"anis": {
//													"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDN43DEN18", 
//													"attrs": []
//												}
//												
//											}
//										]
//									}, 
//									"funcs": {
//										"jaxId": "1FDN43DEN19", 
//										"funcs": [
//											{
//												"jaxId": "1FDN4616Q0", "type": "object", "def": "CdyFunc", "name": "OnClick", "info": "函数", "tip": "", 
//												"args": {
//													"name": "args", "type": "object", "def": "CdyDocObjJSON", "jaxId": "1FDN46ELL0", 
//													"attrs": {}
//												}, 
//												"attrs": {"Mockup Result":"\"\""}
//											}
//										]
//									}
//									
//								}
//							]
//							
//						},
//						{
//							"type": "object", "def": "HudObj", "jaxId": "1FDCCENOJ0", 
//							"attrs": {
//								"locked": "0", "id": "\"BoxLog\"", "x": "32", "y": "80", "w": "\"FW-64\"", "h": "\"FH-200\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//								"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0"
//							}, 
//							"faces": {
//								"jaxId": "1FDCCGGGL4", 
//								"entrys": [
//									{
//										"jaxId": "1FDCCGGGL5", "entryId": "1FDBIT1P10", "faceName": "check", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL6", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL7", "entryId": "1FDBIUSNA0", "faceName": "install", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL8", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL9", "entryId": "1FDBJ276J0", "faceName": "update", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL10", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL11", "entryId": "1FDBKAE2F0", "faceName": "checked", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL12", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL13", "entryId": "1FDBKDMT60", "faceName": "installed", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL14", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL15", "entryId": "1FDBKDTLG0", "faceName": "updated", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL16", 
//											"attrs": []
//										}
//										
//									},
//									{
//										"jaxId": "1FDCCGGGL17", "entryId": "1FDCCC2J50", "faceName": "work", 
//										"attrs": {"display":"Show"}, 
//										"anis": {
//											"name": "Animation", "type": "object", "def": "ani", "jaxId": "1FDCCGGGL18", 
//											"attrs": []
//										}
//										
//									}
//								]
//							}, 
//							"funcs": {"jaxId":"1FDCCGGGL19","funcs":[]}, 
//							"subs": [
//								{
//									"type": "object", "def": "HudBox", "jaxId": "1FOS177MB0", 
//									"attrs": {
//										"locked": "0", "id": "\"BG\"", "x": "-5", "y": "-5", "w": "\"FW+10\"", "h": "\"FH+10\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//										"display": "Show", "clip": "On", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[255,255,255,1]", "border": "1", 
//										"borderStyle": "Solid", "borderColor": "[79,79,79,1]", "coner": "4", "gradient": "\"\"", "shadow": "1", "shadowX": "0", "shadowY": "2", "shadowBlur": "8", 
//										"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//									}, 
//									"funcs": {"jaxId":"1FOS177MB2","funcs":[]}, 
//									"subs": [
//										{
//											"type": "object", "def": "HudBox", "jaxId": "1FOS47NBG0", 
//											"attrs": {
//												"locked": "0", "id": "\"\"", "x": "0", "y": "0", "w": "\"FW\"", "h": "24", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//												"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[255,255,255,1]", "border": "0", "borderStyle": "Solid", 
//												"borderColor": "[56,56,56,1]", "coner": "0", "gradient": "\"linear-gradient(#E8E8E8, #B0B0B0)\"", "shadow": "0", "shadowX": "2", "shadowY": "2", 
//												"shadowBlur": "3", "shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//											}, 
//											"funcs": {"jaxId":"1FOS47NBG2","funcs":[]}, 
//											"subs": [
//												{
//													"type": "object", "def": "HudBox", "jaxId": "1FOS4J9FH3", 
//													"attrs": {
//														"locked": "0", "id": "\"\"", "x": "0", "y": "24", "w": "\"FW\"", "h": "1", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[80,80,80,1]", "border": "0", "borderStyle": "Solid", 
//														"borderColor": "[0,0,0,1]", "coner": "0", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", "shadowSpread": "0", 
//														"shadowColor": "[0,0,0,0.5]"
//													}, 
//													"funcs": {"jaxId":"1FOS4J9FH5","funcs":[]}, "subs": []
//												},
//												{
//													"type": "object", "def": "HudBox", "jaxId": "1FOS6C0QN0", 
//													"attrs": {
//														"locked": "1", "id": "\"\"", "x": "6", "y": "4", "w": "16", "h": "16", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[190,190,190,1]", "border": "1", 
//														"borderStyle": "Solid", "borderColor": "[80,80,80,1]", "coner": "8", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", 
//														"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//													}, 
//													"funcs": {"jaxId":"1FOS6C0QN2","funcs":[]}, "subs": []
//												},
//												{
//													"type": "object", "def": "HudBox", "jaxId": "1FOS6C1VI0", 
//													"attrs": {
//														"locked": "0", "id": "\"\"", "x": "26", "y": "4", "w": "16", "h": "16", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[190,190,190,1]", "border": "1", 
//														"borderStyle": "Solid", "borderColor": "[80,80,80,1]", "coner": "8", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", 
//														"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//													}, 
//													"funcs": {"jaxId":"1FOS6C1VJ0","funcs":[]}, "subs": []
//												},
//												{
//													"type": "object", "def": "HudBox", "jaxId": "1FOS6CM6P0", 
//													"attrs": {
//														"locked": "0", "id": "\"\"", "x": "46", "y": "4", "w": "16", "h": "16", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[190,190,190,1]", "border": "1", 
//														"borderStyle": "Solid", "borderColor": "[80,80,80,1]", "coner": "8", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", 
//														"shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//													}, 
//													"funcs": {"jaxId":"1FOS6CM6Q0","funcs":[]}, "subs": []
//												},
//												{
//													"type": "object", "def": "HudImage", "jaxId": "1FOS7N8VE0", 
//													"attrs": {
//														"locked": "0", "id": "\"\"", "x": "80", "y": "1", "w": "22", "h": "22", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "image": "assets/home.svg", "autoSize": "0", 
//														"fitSize": "1"
//													}, 
//													"funcs": {"jaxId":"1FOS7N8VE2","funcs":[]}, "subs": []
//												}
//											]
//											
//										},
//										{
//											"type": "object", "def": "HudBox", "jaxId": "1FOS9FLH20", 
//											"attrs": {
//												"locked": "0", "id": "\"\"", "x": "0", "y": "\"FH-20\"", "w": "\"FW\"", "h": "20", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//												"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[200,200,200,1]", 
//												"border": "0", "borderStyle": "Solid", "borderColor": "[0,0,0,1]", "coner": "0", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", 
//												"shadowBlur": "3", "shadowSpread": "0", "shadowColor": "[0,0,0,0.5]"
//											}, 
//											"funcs": {"jaxId":"1FOS9FLH21","funcs":[]}, 
//											"subs": [
//												{
//													"type": "object", "def": "HudBox", "jaxId": "1FOS9GC3A0", 
//													"attrs": {
//														"locked": "0", "id": "\"\"", "x": "0", "y": "0", "w": "\"FW\"", "h": "1", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//														"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "color": "[80,80,80,1]", "border": "0", "borderStyle": "Solid", 
//														"borderColor": "[0,0,0,1]", "coner": "0", "gradient": "\"\"", "shadow": "0", "shadowX": "2", "shadowY": "2", "shadowBlur": "3", "shadowSpread": "0", 
//														"shadowColor": "[0,0,0,0.5]"
//													}, 
//													"funcs": {"jaxId":"1FOS9GC3A1","funcs":[]}, "subs": []
//												},
//												{
//													"type": "object", "def": "HudTxt", "jaxId": "1FOS9QEC12", 
//													"attrs": {
//														"locked": "1", "id": "\"TxtBtm\"", "x": "10", "y": "0", "w": "950", "h": "20", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//														"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "text": "\"Setup may take a moment to complete on Chrome\"", 
//														"color": "[60,60,60]", "autoSizeW": "0", "autoSizeH": "0", "select": "0", "wrap": "0", "ellipsis": "0", "alignH": "Left", "alignV": "Center", 
//														"font": "\"\"", "fontSize": "14", "bold": "0", "italic": "0", "underline": "0"
//													}, 
//													"funcs": {"jaxId":"1FOS9QEC14","funcs":[]}, "subs": []
//												}
//											]
//											
//										}
//									]
//									
//								},
//								{
//									"type": "object", "def": "HudTxt", "jaxId": "1FDCCV4S50", 
//									"attrs": {
//										"locked": "0", "id": "\"TxtState\"", "x": "100", "y": "0", "w": "\"FW\"", "h": "20", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//										"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "text": "\"setup --- setup.sh --- 80x25\"", 
//										"color": "[0,0,0]", "autoSizeW": "0", "autoSizeH": "0", "select": "0", "wrap": "0", "ellipsis": "0", "alignH": "Left", "alignV": "Top", "font": "\"\"", 
//										"fontSize": "#appCfg.txtSize.mid", "bold": "0", "italic": "0", "underline": "0"
//									}, 
//									"funcs": {"jaxId":"1FDCCV4S52","funcs":[]}, "subs": []
//								},
//								{
//									"type": "object", "def": "HudObj", "jaxId": "1FOS3E92J0", 
//									"attrs": {
//										"locked": "0", "id": "\"BoxLogText\"", "x": "0", "y": "24", "w": "\"FW\"", "h": "\"FH-48\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//										"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0"
//									}, 
//									"funcs": {"jaxId":"1FOS3E92J2","funcs":[]}, "subs": []
//								}
//							]
//							
//						},
//						{
//							"type": "object", "def": "HudObj", "jaxId": "1FLPI9OUT1", 
//							"attrs": {
//								"locked": "0", "id": "\"BoxFrame\"", "x": "32", "y": "105", "w": "\"FW-64\"", "h": "\"FH-250\"", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", 
//								"display": "Show", "clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0"
//							}, 
//							"funcs": {"jaxId":"1FLPI9OUT3","funcs":[]}, "subs": []
//						},
//						{
//							"type": "object", "def": "HudTxt", "jaxId": "1FOS8BIST0", 
//							"attrs": {
//								"locked": "0", "id": "\"\"", "x": "30", "y": "10", "w": "956", "h": "20", "anchorH": "Left", "anchorV": "Top", "autoLayout": "Off", "display": "Show", 
//								"clip": "Off", "uiEvent": "On", "alpha": "1", "rotate": "0", "cursor": "\"\"", "zIndex": "0", "text": "\"CokeCodes Concept\"", "color": "[180,180,180]", 
//								"autoSizeW": "0", "autoSizeH": "0", "select": "0", "wrap": "0", "ellipsis": "0", "alignH": "Left", "alignV": "Top", "font": "\"\"", "fontSize": "28", 
//								"bold": "0", "italic": "0", "underline": "0"
//							}, 
//							"funcs": {"jaxId":"1FOS8BIST2","funcs":[]}, "subs": []
//						}
//					]
//				}, 
//				"notes": {
//					"type": "object", "def": "HudNote", "jaxId": "1FDAD06P77", 
//					"attrs": {"locked":"0"}, "faces": null, 
//					"viewFaces": {"jaxId":"1FDAD06P79","entrys":[]}, "subs": []
//				}
//			}
//		}/*Doc}#*/;
//	}

//Auto genterated by Cody
var entryUI=UIInstall;
/*#{AppEnv-Pre*/
let jaxDiv=document.getElementById("JAXAppFrame");
var jaxApp,jaxEnv,docPath,diskPath;

jaxDiv.style.height=window.innerHeight+"px";
jaxDiv.style.background="#FAFAFA";

//找到diskpath，根据diskpath可以区分开发环境还是部署环境:
docPath=document.location.href;
let pos1=docPath.indexOf("/disks/");
if(pos1>0){
	pos1+="/disks/".length;
	let pos2=docPath.indexOf("/",pos1);
	diskPath=docPath.substring(pos1,pos2);
	console.log("Disk Path: "+diskPath);
}else {
	diskPath=null;
}
CCWorker.diskPath=diskPath;

document.title="Setup Terminal";

jaxEnv=new JAXEnv(jaxDiv);
window.jaxApp=jaxApp=jaxEnv.createApp();

//先初始化JAX的文件系统，再启动App:
CCDisk.init(jaxApp).then(()=>{
	jaxApp.appCfg=appCfg;
	jaxApp.textLib=textLib["EN"];
	jaxApp.appData=appData;
	initData();
});
//----------------------------------------------------------------------------
//初始化数据:
function initData(){
	let result;
	result=appData.initData(jaxEnv);
	if(result instanceof Promise){
		result.then(startApp,(error)=>{jaxEnv.logError(error);});
	}else {
		startApp();
	}
}

//----------------------------------------------------------------------------
//启动App:
function startApp() {
	var appDef, appState;

	appState=jaxHudState(jaxEnv,{
/*}#AppEnv-Pre*/
/*#{AppEnv-Mid*/
	});

/*}#AppEnv-Mid*/
/*#{AppEnv-Post*/
	appDef={
		layers: [
			{
				appState:appState,
				id: "UILayer", x: 0, y: 0, ofW: "FW", ofH: "FH",
				items: [
					{
						type:"dock",id:"appDock",x:0,y:0,w:"FW",h:"FH",autoLayout:1,
						ui:entryUI(jaxApp)
					},					
				]
			},
		],
		UILayer:null,TipBox:null,
		DlgBGBox:null,
		OnCreate:function(){
		}
	};
	jaxEnv.initApp(appDef);
/*}#AppEnv-Post*/
/*#{AppEnv-End*/
}
/*}#AppEnv-End*/

//Auto genterated by Cody
/*Cody Project Doc*/
//	
//	function $$prjDoc() {
//		return /*#{Doc*/{
//			"jaxId": "1FD92U5OC0", "args": {"entryUI":"\"UIInstall\"","language":"EN"}
//		}/*Doc}#*/;
//	}

</script>
</body>
</html>
